Skip to content

Commit

Permalink
Avoid use of reflection-based deserialization in Java model (#194)
Browse files Browse the repository at this point in the history
* Avoid use of reflection-based deserialization in Java model
* Sort `Set` of TypeAdapters by name to ensure stability of generated output
* Added String extension function `replacingNonAlphaNumericsWith`
  • Loading branch information
RicoYao authored and rahul-malik committed Mar 20, 2019
1 parent 02d18ba commit d467436
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 158 deletions.
48 changes: 30 additions & 18 deletions Examples/Java/Sources/Board.java
Expand Up @@ -375,11 +375,22 @@ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
public static class BoardTypeAdapter extends TypeAdapter<Board> {

final private TypeAdapter<Board> delegateTypeAdapter;
final private TypeAdapter<JsonElement> elementTypeAdapter;

final private TypeAdapter<Date> dateTypeAdapter;
final private TypeAdapter<Image> imageTypeAdapter;
final private TypeAdapter<Map<String, Integer>> map_String__Integer_TypeAdapter;
final private TypeAdapter<Map<String, String>> map_String__String_TypeAdapter;
final private TypeAdapter<Set<User>> set_User_TypeAdapter;
final private TypeAdapter<String> stringTypeAdapter;

public BoardTypeAdapter(Gson gson, BoardTypeAdapterFactory factory, TypeToken typeToken) {
this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken);
this.elementTypeAdapter = gson.getAdapter(JsonElement.class);
this.dateTypeAdapter = gson.getAdapter(Date.class).nullSafe();
this.imageTypeAdapter = gson.getAdapter(Image.class).nullSafe();
this.map_String__Integer_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, Integer>>(){}).nullSafe();
this.map_String__String_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, String>>(){}).nullSafe();
this.set_User_TypeAdapter = gson.getAdapter(new TypeToken<Set<User>>(){}).nullSafe();
this.stringTypeAdapter = gson.getAdapter(String.class).nullSafe();
}

@Override
Expand All @@ -393,43 +404,44 @@ public Board read(JsonReader reader) throws IOException {
reader.nextNull();
return null;
}
JsonElement tree = this.elementTypeAdapter.read(reader);
Board model = this.delegateTypeAdapter.fromJsonTree(tree);
Set<String> keys = tree.getAsJsonObject().keySet();
for (String key : keys) {
switch (key) {
Builder builder = Board.builder();
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
switch (name) {
case ("id"):
model._bits |= ID_SET;
builder.setUid(stringTypeAdapter.read(reader));
break;
case ("contributors"):
model._bits |= CONTRIBUTORS_SET;
builder.setContributors(set_User_TypeAdapter.read(reader));
break;
case ("counts"):
model._bits |= COUNTS_SET;
builder.setCounts(map_String__Integer_TypeAdapter.read(reader));
break;
case ("created_at"):
model._bits |= CREATED_AT_SET;
builder.setCreatedAt(dateTypeAdapter.read(reader));
break;
case ("creator"):
model._bits |= CREATOR_SET;
builder.setCreator(map_String__String_TypeAdapter.read(reader));
break;
case ("description"):
model._bits |= DESCRIPTION_SET;
builder.setDescription(stringTypeAdapter.read(reader));
break;
case ("image"):
model._bits |= IMAGE_SET;
builder.setImage(imageTypeAdapter.read(reader));
break;
case ("name"):
model._bits |= NAME_SET;
builder.setName(stringTypeAdapter.read(reader));
break;
case ("url"):
model._bits |= URL_SET;
builder.setUrl(stringTypeAdapter.read(reader));
break;
default:
break;
reader.skipValue();
}
}
return model;
reader.endObject();
return builder.build();
}
}
}
128 changes: 90 additions & 38 deletions Examples/Java/Sources/Everything.java
Expand Up @@ -1016,11 +1016,62 @@ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
public static class EverythingTypeAdapter extends TypeAdapter<Everything> {

final private TypeAdapter<Everything> delegateTypeAdapter;
final private TypeAdapter<JsonElement> elementTypeAdapter;

final private TypeAdapter<Boolean> booleanTypeAdapter;
final private TypeAdapter<Date> dateTypeAdapter;
final private TypeAdapter<Double> doubleTypeAdapter;
final private TypeAdapter<EverythingIntEnum> everythingIntEnumTypeAdapter;
final private TypeAdapter<EverythingPolymorphicProp> everythingPolymorphicPropTypeAdapter;
final private TypeAdapter<EverythingStringEnum> everythingStringEnumTypeAdapter;
final private TypeAdapter<Integer> integerTypeAdapter;
final private TypeAdapter<List<Integer>> list_Integer_TypeAdapter;
final private TypeAdapter<List<List<User>>> list_List_User__TypeAdapter;
final private TypeAdapter<List<Map<String, User>>> list_Map_String__User__TypeAdapter;
final private TypeAdapter<List<Object>> list_Object_TypeAdapter;
final private TypeAdapter<List<String>> list_String_TypeAdapter;
final private TypeAdapter<List<User>> list_User_TypeAdapter;
final private TypeAdapter<Map<String, EverythingMapPolymorphicValues>> map_String__EverythingMapPolymorphicValues_TypeAdapter;
final private TypeAdapter<Map<String, Integer>> map_String__Integer_TypeAdapter;
final private TypeAdapter<Map<String, List<User>>> map_String__List_User__TypeAdapter;
final private TypeAdapter<Map<String, Map<String, Object>>> map_String__Map_String__Object__TypeAdapter;
final private TypeAdapter<Map<String, Object>> map_String__Object_TypeAdapter;
final private TypeAdapter<Map<String, String>> map_String__String_TypeAdapter;
final private TypeAdapter<Map<String, User>> map_String__User_TypeAdapter;
final private TypeAdapter<Set<Integer>> set_Integer_TypeAdapter;
final private TypeAdapter<Set<Object>> set_Object_TypeAdapter;
final private TypeAdapter<Set<String>> set_String_TypeAdapter;
final private TypeAdapter<Set<User>> set_User_TypeAdapter;
final private TypeAdapter<String> stringTypeAdapter;
final private TypeAdapter<User> userTypeAdapter;

public EverythingTypeAdapter(Gson gson, EverythingTypeAdapterFactory factory, TypeToken typeToken) {
this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken);
this.elementTypeAdapter = gson.getAdapter(JsonElement.class);
this.booleanTypeAdapter = gson.getAdapter(Boolean.class).nullSafe();
this.dateTypeAdapter = gson.getAdapter(Date.class).nullSafe();
this.doubleTypeAdapter = gson.getAdapter(Double.class).nullSafe();
this.everythingIntEnumTypeAdapter = gson.getAdapter(EverythingIntEnum.class).nullSafe();
this.everythingPolymorphicPropTypeAdapter = gson.getAdapter(EverythingPolymorphicProp.class).nullSafe();
this.everythingStringEnumTypeAdapter = gson.getAdapter(EverythingStringEnum.class).nullSafe();
this.integerTypeAdapter = gson.getAdapter(Integer.class).nullSafe();
this.list_Integer_TypeAdapter = gson.getAdapter(new TypeToken<List<Integer>>(){}).nullSafe();
this.list_List_User__TypeAdapter = gson.getAdapter(new TypeToken<List<List<User>>>(){}).nullSafe();
this.list_Map_String__User__TypeAdapter = gson.getAdapter(new TypeToken<List<Map<String, User>>>(){}).nullSafe();
this.list_Object_TypeAdapter = gson.getAdapter(new TypeToken<List<Object>>(){}).nullSafe();
this.list_String_TypeAdapter = gson.getAdapter(new TypeToken<List<String>>(){}).nullSafe();
this.list_User_TypeAdapter = gson.getAdapter(new TypeToken<List<User>>(){}).nullSafe();
this.map_String__EverythingMapPolymorphicValues_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, EverythingMapPolymorphicValues>>(){}).nullSafe();
this.map_String__Integer_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, Integer>>(){}).nullSafe();
this.map_String__List_User__TypeAdapter = gson.getAdapter(new TypeToken<Map<String, List<User>>>(){}).nullSafe();
this.map_String__Map_String__Object__TypeAdapter = gson.getAdapter(new TypeToken<Map<String, Map<String, Object>>>(){}).nullSafe();
this.map_String__Object_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, Object>>(){}).nullSafe();
this.map_String__String_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, String>>(){}).nullSafe();
this.map_String__User_TypeAdapter = gson.getAdapter(new TypeToken<Map<String, User>>(){}).nullSafe();
this.set_Integer_TypeAdapter = gson.getAdapter(new TypeToken<Set<Integer>>(){}).nullSafe();
this.set_Object_TypeAdapter = gson.getAdapter(new TypeToken<Set<Object>>(){}).nullSafe();
this.set_String_TypeAdapter = gson.getAdapter(new TypeToken<Set<String>>(){}).nullSafe();
this.set_User_TypeAdapter = gson.getAdapter(new TypeToken<Set<User>>(){}).nullSafe();
this.stringTypeAdapter = gson.getAdapter(String.class).nullSafe();
this.userTypeAdapter = gson.getAdapter(User.class).nullSafe();
}

@Override
Expand All @@ -1034,103 +1085,104 @@ public Everything read(JsonReader reader) throws IOException {
reader.nextNull();
return null;
}
JsonElement tree = this.elementTypeAdapter.read(reader);
Everything model = this.delegateTypeAdapter.fromJsonTree(tree);
Set<String> keys = tree.getAsJsonObject().keySet();
for (String key : keys) {
switch (key) {
Builder builder = Everything.builder();
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
switch (name) {
case ("array_prop"):
model._bits |= ARRAY_PROP_SET;
builder.setArrayProp(list_Object_TypeAdapter.read(reader));
break;
case ("boolean_prop"):
model._bits |= BOOLEAN_PROP_SET;
builder.setBooleanProp(booleanTypeAdapter.read(reader));
break;
case ("date_prop"):
model._bits |= DATE_PROP_SET;
builder.setDateProp(dateTypeAdapter.read(reader));
break;
case ("int_enum"):
model._bits |= INT_ENUM_SET;
builder.setIntEnum(everythingIntEnumTypeAdapter.read(reader));
break;
case ("int_prop"):
model._bits |= INT_PROP_SET;
builder.setIntProp(integerTypeAdapter.read(reader));
break;
case ("list_polymorphic_values"):
model._bits |= LIST_POLYMORPHIC_VALUES_SET;
builder.setListPolymorphicValues(list_Object_TypeAdapter.read(reader));
break;
case ("list_with_list_and_other_model_values"):
model._bits |= LIST_WITH_LIST_AND_OTHER_MODEL_VALUES_SET;
builder.setListWithListAndOtherModelValues(list_List_User__TypeAdapter.read(reader));
break;
case ("list_with_map_and_other_model_values"):
model._bits |= LIST_WITH_MAP_AND_OTHER_MODEL_VALUES_SET;
builder.setListWithMapAndOtherModelValues(list_Map_String__User__TypeAdapter.read(reader));
break;
case ("list_with_object_values"):
model._bits |= LIST_WITH_OBJECT_VALUES_SET;
builder.setListWithObjectValues(list_String_TypeAdapter.read(reader));
break;
case ("list_with_other_model_values"):
model._bits |= LIST_WITH_OTHER_MODEL_VALUES_SET;
builder.setListWithOtherModelValues(list_User_TypeAdapter.read(reader));
break;
case ("list_with_primitive_values"):
model._bits |= LIST_WITH_PRIMITIVE_VALUES_SET;
builder.setListWithPrimitiveValues(list_Integer_TypeAdapter.read(reader));
break;
case ("map_polymorphic_values"):
model._bits |= MAP_POLYMORPHIC_VALUES_SET;
builder.setMapPolymorphicValues(map_String__EverythingMapPolymorphicValues_TypeAdapter.read(reader));
break;
case ("map_prop"):
model._bits |= MAP_PROP_SET;
builder.setMapProp(map_String__Object_TypeAdapter.read(reader));
break;
case ("map_with_list_and_other_model_values"):
model._bits |= MAP_WITH_LIST_AND_OTHER_MODEL_VALUES_SET;
builder.setMapWithListAndOtherModelValues(map_String__List_User__TypeAdapter.read(reader));
break;
case ("map_with_map_and_other_model_values"):
model._bits |= MAP_WITH_MAP_AND_OTHER_MODEL_VALUES_SET;
builder.setMapWithMapAndOtherModelValues(map_String__Map_String__Object__TypeAdapter.read(reader));
break;
case ("map_with_object_values"):
model._bits |= MAP_WITH_OBJECT_VALUES_SET;
builder.setMapWithObjectValues(map_String__String_TypeAdapter.read(reader));
break;
case ("map_with_other_model_values"):
model._bits |= MAP_WITH_OTHER_MODEL_VALUES_SET;
builder.setMapWithOtherModelValues(map_String__User_TypeAdapter.read(reader));
break;
case ("map_with_primitive_values"):
model._bits |= MAP_WITH_PRIMITIVE_VALUES_SET;
builder.setMapWithPrimitiveValues(map_String__Integer_TypeAdapter.read(reader));
break;
case ("number_prop"):
model._bits |= NUMBER_PROP_SET;
builder.setNumberProp(doubleTypeAdapter.read(reader));
break;
case ("other_model_prop"):
model._bits |= OTHER_MODEL_PROP_SET;
builder.setOtherModelProp(userTypeAdapter.read(reader));
break;
case ("polymorphic_prop"):
model._bits |= POLYMORPHIC_PROP_SET;
builder.setPolymorphicProp(everythingPolymorphicPropTypeAdapter.read(reader));
break;
case ("set_prop"):
model._bits |= SET_PROP_SET;
builder.setSetProp(set_Object_TypeAdapter.read(reader));
break;
case ("set_prop_with_other_model_values"):
model._bits |= SET_PROP_WITH_OTHER_MODEL_VALUES_SET;
builder.setSetPropWithOtherModelValues(set_User_TypeAdapter.read(reader));
break;
case ("set_prop_with_primitive_values"):
model._bits |= SET_PROP_WITH_PRIMITIVE_VALUES_SET;
builder.setSetPropWithPrimitiveValues(set_Integer_TypeAdapter.read(reader));
break;
case ("set_prop_with_values"):
model._bits |= SET_PROP_WITH_VALUES_SET;
builder.setSetPropWithValues(set_String_TypeAdapter.read(reader));
break;
case ("string_enum"):
model._bits |= STRING_ENUM_SET;
builder.setStringEnum(everythingStringEnumTypeAdapter.read(reader));
break;
case ("string_prop"):
model._bits |= STRING_PROP_SET;
builder.setStringProp(stringTypeAdapter.read(reader));
break;
case ("type"):
model._bits |= TYPE_SET;
builder.setType(stringTypeAdapter.read(reader));
break;
case ("uri_prop"):
model._bits |= URI_PROP_SET;
builder.setUriProp(stringTypeAdapter.read(reader));
break;
default:
break;
reader.skipValue();
}
}
return model;
reader.endObject();
return builder.build();
}
}

Expand Down
28 changes: 16 additions & 12 deletions Examples/Java/Sources/Image.java
Expand Up @@ -195,11 +195,14 @@ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
public static class ImageTypeAdapter extends TypeAdapter<Image> {

final private TypeAdapter<Image> delegateTypeAdapter;
final private TypeAdapter<JsonElement> elementTypeAdapter;

final private TypeAdapter<Integer> integerTypeAdapter;
final private TypeAdapter<String> stringTypeAdapter;

public ImageTypeAdapter(Gson gson, ImageTypeAdapterFactory factory, TypeToken typeToken) {
this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken);
this.elementTypeAdapter = gson.getAdapter(JsonElement.class);
this.integerTypeAdapter = gson.getAdapter(Integer.class).nullSafe();
this.stringTypeAdapter = gson.getAdapter(String.class).nullSafe();
}

@Override
Expand All @@ -213,25 +216,26 @@ public Image read(JsonReader reader) throws IOException {
reader.nextNull();
return null;
}
JsonElement tree = this.elementTypeAdapter.read(reader);
Image model = this.delegateTypeAdapter.fromJsonTree(tree);
Set<String> keys = tree.getAsJsonObject().keySet();
for (String key : keys) {
switch (key) {
Builder builder = Image.builder();
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
switch (name) {
case ("height"):
model._bits |= HEIGHT_SET;
builder.setHeight(integerTypeAdapter.read(reader));
break;
case ("url"):
model._bits |= URL_SET;
builder.setUrl(stringTypeAdapter.read(reader));
break;
case ("width"):
model._bits |= WIDTH_SET;
builder.setWidth(integerTypeAdapter.read(reader));
break;
default:
break;
reader.skipValue();
}
}
return model;
reader.endObject();
return builder.build();
}
}
}

0 comments on commit d467436

Please sign in to comment.