GSON not calling my TypeAdapter for a type which i

2020-05-24 20:18发布

问题:

GSON appears to be doing some kind of trick where it looks at the internal fields of my JavaBeans instead of using the publically-accessible property information. Unfortunately this won't fly for us because our magically-created beans are full of private fields which I don't want it to store off.

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

This gives:

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

And of course, never calls my type adapter, which seemingly makes it impossible to get any other behaviour.

回答1:

I had the same issue, with version 2.3.1 of Gson. I got it working by using

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

instead of

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


回答2:

Current release of GSON does not work this way. This will serialize your type using the adapter.

gson.toJson(bean, Player.class)

Alternatively you can register the PlayerTypeAdapter for MagicPlayer.class and your existing code will work. GSON looks up the TypeAdapter by the concrete (or top level) type only. So you will have to register a custom type adapter for every concrete type you may encounter.

There is TypeHeirarchyAdapter for when you want the same TypeAdapter to be used for all extending classes of a given type. I have not had good luck with this though and have not really spent time looking into why it has not worked well for me. Here is some relevant discussion: https://groups.google.com/forum/?fromgroups=#!searchin/google-gson/interface/google-gson/0ebOxifqwb0/OXSCNTiLpBQJ



回答3:

Why it does not work:

  1. PlayerTypeAdapter should implements JsonSerializer. Does it?

  2. If it does - than should work. It work perfect for me, so don't see reason why it does not work for you. Start you application in debug, put breakpoints and checkout. There should be some reason.

In your test where is Gson builder with adapter? You should change it:

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


标签: java json gson