java - Make GSON accept single objects where it expects arrays -


i have bunch of model classes have fields of type list<x> x 1 of many things (e.g. string, integer, of own types). i'm using gson parse json represenations of these models. problem server i'm deal (which beyond control) somehow removed singleton arrays , replaces them contained object. example, instead of returning:

{   "foo": [ "bar"],   "bleh": [ { "some": "object" } ] } 

it returns:

{   "foo": "bar",   "bleh": { "some": "object" } } 

now assume java model class this:

public class model {    private list<string> foo;    private list<someobject> bleh; } 

currently causes gson throw exception because finds begin_string or begin_object expects begin_array.

for arrays or lists of strings solved using typeadapter<list<string>>. problem have lists many different element types , don't want write separate typeadapter each case. nor have been able generic typeadapter<list<?>>, because @ point need know type. there way configure gson smart enough turn single objects or values arrays/lists? or in other words, "pretend" [ , ] there expects find them doesn't?

but problem have lists many different element types , don't want write separate typeadapter each case. nor have been able generic typeadapter>, because @ point need know type.

this type adapter factories designed for: can control every type in gson instance configuration.

final class alwayslisttypeadapterfactory<e>         implements typeadapterfactory {      // gson can instantiate     private alwayslisttypeadapterfactory() {     }      @override     public <t> typeadapter<t> create(final gson gson, final typetoken<t> typetoken) {         // if it's not list -- delegate job gson , let pick best type adapter         if ( !list.class.isassignablefrom(typetoken.getrawtype()) ) {             return null;         }         // resolving list parameter type         final type elementtype = resolvetypeargument(typetoken.gettype());         @suppresswarnings("unchecked")         final typeadapter<e> elementtypeadapter = (typeadapter<e>) gson.getadapter(typetoken.get(elementtype));         // note always-list type adapter made null-safe, don't have check nulls ourselves         @suppresswarnings("unchecked")         final typeadapter<t> alwayslisttypeadapter = (typeadapter<t>) new alwayslisttypeadapter<>(elementtypeadapter).nullsafe();         return alwayslisttypeadapter;     }      private static type resolvetypeargument(final type type) {         // given type not parameterized?         if ( !(type instanceof parameterizedtype) ) {             // no, raw             return object.class;         }         final parameterizedtype parameterizedtype = (parameterizedtype) type;         return parameterizedtype.getactualtypearguments()[0];     }      private static final class alwayslisttypeadapter<e>             extends typeadapter<list<e>> {          private final typeadapter<e> elementtypeadapter;          private alwayslisttypeadapter(final typeadapter<e> elementtypeadapter) {             this.elementtypeadapter = elementtypeadapter;         }          @override         public void write(final jsonwriter out, final list<e> list) {             throw new unsupportedoperationexception();         }          @override         public list<e> read(final jsonreader in)                 throws ioexception {             // detect list "type"             final list<e> list = new arraylist<>();             final jsontoken token = in.peek();             switch ( token ) {             case begin_array:                 // if it's regular list, consume [, <all elements>, , ]                 in.beginarray();                 while ( in.hasnext() ) {                     list.add(elementtypeadapter.read(in));                 }                 in.endarray();                 break;             case begin_object:             case string:             case number:             case boolean:                 // object or primitive? add current value result list                 list.add(elementtypeadapter.read(in));                 break;             case null:                 throw new assertionerror("must never happen: check if type adapter configured .nullsafe()");             case name:             case end_array:             case end_object:             case end_document:                 throw new malformedjsonexception("unexpected token: " + token);             default:                 throw new assertionerror("must never happen: " + token);             }             return list;         }      }  } 

now have tell gson which fields not well-formed. of course, might configure whole gson instance accept such lists, let more precise using @jsonadapter annotation:

final class model {      @jsonadapter(alwayslisttypeadapterfactory.class)     final list<string> foo = null;      @jsonadapter(alwayslisttypeadapterfactory.class)     final list<someobject> bleh = null;      @override     public string tostring() {         return "model{" + "foo=" + foo + ", bleh=" + bleh + '}';     }  }  final class someobject {      final string = null;      @override     public string tostring() {         return "someobject{" + "some='" + + '\'' + '}';     }  } 

test data:

single.json

{     "foo": "bar",     "bleh": {"some": "object"} } 

list.json

{     "foo": ["bar"],     "bleh": [{"some": "object"}] } 

example:

private static final gson gson = new gson();  public static void main(final string... args)         throws ioexception {     ( final string resource : immutablelist.of("single.json", "list.json") ) {         try ( final jsonreader jsonreader = getpackageresourcejsonreader(q43412261.class, resource) ) {             final model model = gson.fromjson(jsonreader, model.class);             system.out.println(model);         }     } } 

and output:

model{foo=[bar], bleh=[someobject{some='object'}]}
model{foo=[bar], bleh=[someobject{some='object'}]}


Comments

Popular posts from this blog

php - Permission denied. Laravel linux server -

google bigquery - Delta between query execution time and Java query call to finish -

python - Pandas two dataframes multiplication? -