38

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.

2
  • Could you add the code that calls Gson.toJson() ? Commented May 18, 2012 at 5:31
  • It's not clear this is the same problem, but I ran into something similar a while ago, perhaps it will help you: stackoverflow.com/questions/5952595/… Commented Apr 20, 2014 at 5:09

3 Answers 3

77

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()) 
Sign up to request clarification or add additional context in comments.

1 Comment

This one should be accepted as an answer. Works with java.util.Calendar (actual type is java.util.GregorianCalendar)
9

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

2 Comments

This answers the main part of the question about why it doesn't work. It doesn't exactly solve the problem or make GSON usable in any way, because relying on the code to tell it the type of everything is never going to work. e.g., there is another place where I have a List<Object> where each object could be any type. Now what am I supposed to do?
The second part of the question explains what to do. For each concrete type you need to register the TypeAdapter you want to use.
-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)); } 

3 Comments

You can see in the question above how PlayerTypeAdapter is implemented. I put a breakpoint on the line where I am throwing the exception, but the line is never reached. Ergo, Gson is not calling my serialiser. There must be something else I'm supposed to do. Either that, or Gson doesn't call type adapters for interfaces (which just means I can't use it.)
Okay, updated to remove CGLIB from the equation. Gson still doesn't call my type adapter at any point.
Please read the question before updating your answer any further.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.