I have a JSON object that looks like this
{
\"foo\":{
\"bar\":\"bar\",
\"echo\":\"echo\"
}
}
But then my Java object looks
Unfortunately you cannot do it using @SerializedName since it's used in streamed parsing therefore Gson cannot make any look-aheads to resolve path expressions. However, the idea would be nice, but it would require at the least a subtree to be stored in memory that can be too memory-consuming in some cases. Since JsonSerializer and JsonDeserializer work with JSON trees only, you can easily write your own JSON deserializer that can just omit unnecessary JSON objects (semantically equivalent to the expression you want to have in @SerializedName). So,
// To unwrap the top-most JSON object
final class Wrapper {
Foo foo;
}
final class Foo {
String foo2;
}
The deserializer may be implemented like this (however you should keep in mind that JsonSerializer and JsonDeserializer do not play with a Gson built-in ReflectiveTypeAdapterFactory that actually can process @SerializedName):
final class FooJsonDeserializer
implements JsonDeserializer {
private static final JsonDeserializer fooJsonDeserializer = new FooJsonDeserializer();
private FooJsonDeserializer() {
}
static JsonDeserializer getFooJsonDeserializer() {
return fooJsonDeserializer;
}
@Override
public Foo deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context) {
final JsonObject jsonObject = jsonElement.getAsJsonObject();
final Foo foo = new Foo();
foo.foo2 = jsonObject.get("echo").getAsString();
return foo;
}
}
Example use:
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(Foo.class, getFooJsonDeserializer())
.create();
public static void main(final String... args) {
final Wrapper wrapper = gson.fromJson("{\"foo\":{\"bar\":\"bar\",\"echo\":\"echo\"}}", Wrapper.class);
System.out.println(wrapper.foo.foo2);
}
Output:
echo