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

Popular posts from this blog

ruby - Trying to change last to "x"s to 23 -

jquery - Clone last and append item to closest class -

c - Unrecognised emulation mode: elf_i386 on MinGW32 -