34

GSON 似乎在做某种技巧,它查看我的 JavaBeans 的内部字段,而不是使用可公开访问的属性信息。不幸的是,这对我们来说是行不通的,因为我们神奇地创建的 bean 充满了我不希望它存储的私有字段。

@Test
public void testJson() throws Exception
{
    Player player = new MagicPlayer(); //BeanUtils.createDefault(Player.class);
    player.setName("Alice");

    Gson gson = new GsonBuilder()
        .registerTypeAdapter(Player.class, new PlayerTypeAdapter())
        .create();

    System.out.println(gson.toJson(bean));
}

private static class PlayerTypeAdapter implements JsonSerializer<Player>
{
    @Override
    public JsonElement serialize(Player player, Type type,
                                 JsonSerializationContext context)
    {
        throw new RuntimeException("I got called, woohoo");
    }
}

public static interface Player //extends SupportsPropertyChanges
{
    public String getName();
    public void setName(String name);
}

// Simple implementation simulating what we're doing.
public static class MagicPlayer implements Player
{
    private final String privateStuff = "secret";
    private String name;

    @Override
    public String getName()
    {
        return name;
    }

    @Override
    public void setName(String name)
    {
        this.name = name;
    }
}

这给出了:

{"privateStuff":"secret","name":"Alice"}

当然,永远不要调用我的类型适配器,这似乎使得无法获得任何其他行为。

4

3 回答 3

66

我遇到了同样的问题,Gson 的 2.3.1 版本。我通过使用让它工作

.registerTypeHierarchyAdapter(Player.class, new PlayerTypeAdapter())

代替

.registerTypeAdapter(Player.class, new PlayerTypeAdapter())
于 2015-03-11T17:49:40.610 回答
9

当前版本的 GSON 不能以这种方式工作。这将使用适配器序列化您的类型。

gson.toJson(bean, Player.class)

或者,您可以注册PlayerTypeAdapterforMagicPlayer.class并且您现有的代码将起作用。GSON 仅TypeAdapter按具体(或顶级)类型查找。因此,您必须为可能遇到的每种具体类型注册一个自定义类型适配器。

TypeHeirarchyAdapter当您希望将相同的内容TypeAdapter用于给定类型的所有扩展类时。不过,我对此并不好运,也没有真正花时间研究为什么它对我不起作用。这是一些相关的讨论:https ://groups.google.com/forum/?fromgroups=#!searchin/google-gson/interface/google-gson/0ebOxifqwb0/OXSCNTiLpBQJ

于 2012-08-23T05:15:49.920 回答
-3

为什么它不起作用:

  1. PlayerTypeAdapter 应该实现 JsonSerializer。可以?

  2. 如果确实如此 - 应该工作。它对我来说很完美,所以看不出它对你不起作用的原因。在调试中启动您的应用程序,放置断点并结帐。应该是有原因的。

在您的测试中,带有适配器的 Gson 构建器在哪里?你应该改变它:

public void testJson() throws Exception
{
    Player player = new MagicPlayer(); //BeanUtils.createDefault(Player.class);
    player.setName("Alice");

    // this is wrong if you want adapter
    /* Gson gson = new Gson(); */

    // this is what you nead
     Gson gson = new GsonBuilder()
        .registerTypeAdapter(Player.class, new PlayerTypeAdapter())
        .create();

    System.out.println(gson.toJson(bean));
}
于 2012-05-17T07:14:44.937 回答