Skip to content
This repository was archived by the owner on Feb 1, 2024. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,102 +37,111 @@
*/
class MailChimpObjectTypeAdapter extends TypeAdapter<MailChimpObject> {

static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@Override
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (MailChimpObject.class.isAssignableFrom(type.getRawType())) {
return (TypeAdapter<T>) new MailChimpObjectTypeAdapter(gson, (TypeToken<MailChimpObject>) type);
} else {
return null;
}
}
};

private final Gson gson;
private final Constructor<? extends MailChimpObject> constructor;

@SuppressWarnings("unchecked")
private MailChimpObjectTypeAdapter(Gson gson, TypeToken<MailChimpObject> type) {
this.gson = gson;

try {
this.constructor = ((Class<? extends MailChimpObject>) type.getRawType()).getDeclaredConstructor();
this.constructor.setAccessible(true);
} catch(NoSuchMethodException e) {
throw new IllegalArgumentException("No no-arg counstructor found in "+type.getRawType());
}
}

@Override
public void write(JsonWriter out, MailChimpObject value) throws IOException {
gson.getAdapter(Map.class).write(out, value);
}

@Override
public MailChimpObject read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}

MailChimpObject result;
try {
result = constructor.newInstance();
} catch(Exception e) {
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
}

in.beginObject();
while (in.hasNext()) {
final String key;
if (in.peek() == JsonToken.NAME) {
key = in.nextName();
} else {
key = in.nextString();
}

final Object value;

Type valueType = result.getReflectiveMappingTypes().get(key);
if (valueType != null) {
value = gson.getAdapter(TypeToken.get(valueType)).read(in);
} else {
if (in.peek() == JsonToken.BEGIN_OBJECT) {
value = gson.getAdapter(MailChimpObject.class).read(in);
} else if(in.peek() == JsonToken.BEGIN_ARRAY) {
value = readList(in);
} else {
value = gson.getAdapter(Object.class).read(in);
}
}

if (result.put(key, value) != null) {
throw new JsonSyntaxException("duplicate key: " + key);
}
}
in.endObject();

return result;
}

private List<?> readList(JsonReader in) throws IOException {
List<Object> result = new ArrayList<Object>();
in.beginArray();
while(in.peek() != JsonToken.END_ARRAY) {
final Object element;

if (in.peek() == JsonToken.BEGIN_OBJECT) {
element = gson.getAdapter(MailChimpObject.class).read(in);
} else if(in.peek() == JsonToken.BEGIN_ARRAY) {
element = readList(in);
} else {
element = gson.getAdapter(Object.class).read(in);
}

result.add(element);
}
in.endArray();
return result;
}
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@Override
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (MailChimpObject.class.isAssignableFrom(type.getRawType())) {
return (TypeAdapter<T>) new MailChimpObjectTypeAdapter(gson, (TypeToken<MailChimpObject>) type);
} else {
return null;
}
}
};

private final Gson gson;
private final Constructor<? extends MailChimpObject> constructor;

@SuppressWarnings("unchecked")
private MailChimpObjectTypeAdapter(Gson gson, TypeToken<MailChimpObject> type) {
this.gson = gson;

try {
this.constructor = ((Class<? extends MailChimpObject>) type.getRawType()).getDeclaredConstructor();
this.constructor.setAccessible(true);
} catch(NoSuchMethodException e) {
throw new IllegalArgumentException("No no-arg counstructor found in "+type.getRawType());
}
}

@Override
public void write(JsonWriter out, MailChimpObject value) throws IOException {
gson.getAdapter(Map.class).write(out, value);
}

@Override
public MailChimpObject read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}

MailChimpObject result;
try {
result = constructor.newInstance();
} catch(Exception e) {
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
}

if (in.peek() == JsonToken.BEGIN_ARRAY) {
in.beginArray();
if (in.peek() != JsonToken.END_ARRAY) {
throw new IllegalStateException("Expected empty array as empty mailchimp object.");
}
in.endArray();
return result;
}

in.beginObject();
while (in.hasNext()) {
final String key;
if (in.peek() == JsonToken.NAME) {
key = in.nextName();
} else {
key = in.nextString();
}

final Object value;

Type valueType = result.getReflectiveMappingTypes().get(key);
if (valueType != null) {
value = gson.getAdapter(TypeToken.get(valueType)).read(in);
} else {
if (in.peek() == JsonToken.BEGIN_OBJECT) {
value = gson.getAdapter(MailChimpObject.class).read(in);
} else if(in.peek() == JsonToken.BEGIN_ARRAY) {
value = readList(in);
} else {
value = gson.getAdapter(Object.class).read(in);
}
}

if (result.put(key, value) != null) {
throw new JsonSyntaxException("duplicate key: " + key);
}
}
in.endObject();

return result;
}

private List<?> readList(JsonReader in) throws IOException {
List<Object> result = new ArrayList<Object>();
in.beginArray();
while(in.peek() != JsonToken.END_ARRAY) {
final Object element;

if (in.peek() == JsonToken.BEGIN_OBJECT) {
element = gson.getAdapter(MailChimpObject.class).read(in);
} else if(in.peek() == JsonToken.BEGIN_ARRAY) {
element = readList(in);
} else {
element = gson.getAdapter(Object.class).read(in);
}

result.add(element);
}
in.endArray();
return result;
}
}