【问题标题】:GSON not calling my TypeAdapter for a type which is an interfaceGSON 没有为作为接口的类型调用我的 TypeAdapter
【发布时间】:2012-05-24 18:23:03
【问题描述】:

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

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

【问题讨论】:

  • 能否添加调用 Gson.toJson() 的代码?
  • 不清楚这是同一个问题,但我前段时间遇到过类似的问题,也许它会对你有所帮助:stackoverflow.com/questions/5952595/…

标签: java json gson


【解决方案1】:

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

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

而不是

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

【讨论】:

  • 这个应该被接受为答案。适用于 java.util.Calendar(实际类型为 java.util.GregorianCalendar)
【解决方案2】:

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

gson.toJson(bean, Player.class)

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

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

【讨论】:

  • 这回答了为什么它不起作用的问题的主要部分。它并不能完全解决问题或使 GSON 以任何方式可用,因为依靠代码告诉它一切的类型永远不会起作用。例如,在另一个地方我有一个 List ,其中每个对象都可以是任何类型。现在我该怎么办?
  • 问题的第二部分解释了该怎么做。对于每种具体类型,您需要注册要使用的TypeAdapter
【解决方案3】:

为什么它不起作用:

  1. PlayerTypeAdapter 应该实现 JsonSerializer。是吗?

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

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

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));
}

【讨论】:

  • 您可以在上面的问题中看到 PlayerTypeAdapter 是如何实现的。我在抛出异常的行上放了一个断点,但从未到达该行。因此,Gson 没有调用我的序列化器。我应该还有别的事情要做。要么,要么 Gson 不调用接口的类型适配器(这只是意味着我不能使用它。)
  • 好的,已更新以从等式中删除 CGLIB。 Gson 仍然不会在任何时候调用我的类型适配器。
  • 请在进一步更新您的答案之前阅读问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
相关资源
最近更新 更多