java - GSON deserialization with generic types and generic field names -
let's have structure this:
json:
{ "body": { "cats": [{ "cat": { "id": 1, "title": "cat1" } }, { "cat": { "id": 2, "title": "cat2" } }] } }
and corresponding pojo:
response.class
private final body body;
body.class
private final collection<catwrapper> cats
catwrapper.class
private final cat cat
cat.class
private final int id; private final string title;
but let have same structure, instead of cat
receive truck
{ "body": { "trucks": [{ "truck": { "id": 1, "engine": "big", "wheels" : 12 } }, { "truck": { "id": 2, "engine": "super big", "wheels" : 128 } }] } }
i'm using gson (default retrofit
json parser) on android
, consider while giving solutions.
we use generics here response like:
private final body<listresponse<itemwrapper<t>>
can't since field names specific class.
question:
what can serialize automaticaly without creating many boilerplate classes? don't need separate classes bodycat
, bodytruck
, bodyanyotherclassinthisstructure
, i'm looking way avoid having them.
@edit:
i've change classes (cat, dog -> cat,truck) due inheritance confusion, classes used here example not extends 1 another
one idea define custom generic deserializer. generic type represent concrete class of list's elements wrapped in body
instance.
assuming following classes:
class body<t> { private list<t> list; public body(list<t> list) { this.list = list; } } class cat { private int id; private string title; ... } class truck { private int id; private string engine; private int wheels; ... }
the deserializer assumes structure of json same, in sense have object contains object named "body". assumes value in first key-value pair of body list.
now each element in json array, need again fetch inner object associated each key. deserialize value , put in list.
class customjsondeserializer<t> implements jsondeserializer<body<t>> { private final class<t> clazz; public customjsondeserializer(class<t> clazz) { this.clazz = clazz; } @override public body<t> deserialize(jsonelement json, type typeoft, jsondeserializationcontext context) throws jsonparseexception { jsonobject body = json.getasjsonobject().getasjsonobject("body"); jsonarray arr = body.entryset().iterator().next().getvalue().getasjsonarray(); list<t> list = new arraylist<>(); for(jsonelement element : arr) { jsonelement innerelement = element.getasjsonobject().entryset().iterator().next().getvalue(); list.add(context.deserialize(innerelement, clazz)); } return new body<>(list); } }
for final step, need create corresponding type, instantiate , register adapter in parser. instance trucks:
type trucktype = new typetoken<body<truck>>(){}.gettype(); gson gson = new gsonbuilder() .registertypeadapter(trucktype, new customjsondeserializer<>(truck.class)) .create(); body<truck> body = gson.fromjson(new filereader("file.json"), trucktype);
you can return list directly adapter if want rid of body
class.
with trucks you'll [1_big_12, 2_super big_128]
output , [1_cat1, 2_cat2]
cats.
Comments
Post a Comment