GSON 没有为接口类型调用我的 TypeAdapter

2022-09-01 06:33:52

GSON似乎正在做某种技巧,它查看我的JavaBeans的内部字段,而不是使用可公开访问的属性信息。不幸的是,这对我们来说不会飞,因为我们神奇创造的豆子充满了私人领域,我不希望它储存起来。

@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"}

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


答案 1

我在Gson的2.3.1版本中遇到了同样的问题。我通过使用

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

而不是

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

答案 2

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

gson.toJson(bean, Player.class)

或者,您可以注册 for,您的现有代码将正常工作。GSON 仅按具体(或顶级)类型查找。因此,您必须为可能遇到的每种具体类型注册一个自定义类型适配器。PlayerTypeAdapterMagicPlayer.classTypeAdapter

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