Trouble with Gson Serializing an Arraylist of Pojo'S

Trouble with Gson serializing an ArrayList of POJO's

You need to give Gson information on the specific generic type of List you're using (or any generic type you use with it). Particularly when deserializing JSON, it needs that information to be able to determine what type of object it should deserialize each array element to.

Type listOfTestObject = new TypeToken<List<TestObject>>(){}.getType();
String s = gson.toJson(list, listOfTestObject);
List<TestObject> list2 = gson.fromJson(s, listOfTestObject);

This is documented in the Gson user guide.

Gson and Serializing an ArrayList of Objects with Inheritance

You can't do it this way.

The example you are referring is not targeted to your case. It works in only one case: if you register base type (not type hierarchy) and serialize using gson.toJson(obj, javaClass<Event>()). It will never work for array except you write custom serializer for you events container object too

Generally you need another approach: use TypeAdapterFactory and delegate adapters: GSON: serialize/deserialize object of class, that have registered type hierarchy adapter, using ReflectiveTypeAdapterFactory.Adapter and https://code.google.com/p/google-gson/issues/detail?id=43#c15

I believe this approach is overcomplicated so if you have few types the easiest solution is two serialize these types by hand, field by field via custom serializer and forget about attempts to delegate to default

serializing with gson and back does not work with generic types

It is due to type erasure of generics. You need to use TokenType to retrieve the type information at runtime.

val fromJson = gson1.fromJson<WrapperDto<Person>>(toJson, object: TypeToken<WrapperDto<Person>>() {}.type)

You may also create an extension function like this:

inline fun <reified T> fromJson(json: String): T = Gson().fromJson<T>(json, object: TypeToken<T>() {}.type)

So, you can call fromJson this way:

val fromJson = fromJson<WrapperDto<Person>>(toJson)
//Or
val fromJson: WrapperDto<Person> = fromJson(toJson) //Type inferred

Convert String to ArrayListString using GSON

Boxing structured data in a string where it is unnecessary is a very common design issue across different serialization approaches. Fortunately, Gson can deal with fields like owner_emails (but not message of course).

Merely create a type adapter factory than can create a type adapter for a particular type by substituting the original one and doing a bit of more work. The adapter is supposed to read the payload as string and delegate the string deserialization to the type adapter it substitutes.

public final class JsonStringBoxTypeAdapterFactory
implements TypeAdapterFactory {

private JsonStringBoxTypeAdapterFactory() {
}

@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
final TypeAdapter<T> adapter = gson.getAdapter(typeToken);
return new TypeAdapter<T>() {
@Override
public void write(final JsonWriter out, final T value) {
throw new UnsupportedOperationException(); // TODO
}

@Override
public T read(final JsonReader in)
throws IOException {
return adapter.fromJson(in.nextString());
}
};
}

}
@AllArgsConstructor
@ToString
@EqualsAndHashCode
final class EventData {

@SerializedName("owner_emails")
@JsonAdapter(JsonStringBoxTypeAdapterFactory.class)
List<String> ownerEmails;

}

The unit test below will be green:

final EventData eventData = gson.fromJson(json, EventData.class);
Assertions.assertEquals(new EventData(ImmutableList.of("abcd@xyz.com")), eventData);

That's it.

deserializing generics with gson

Gson has some limitations regarding collections because of Java's type erasure. You can read more about it here.

From your question I see you're using both ArrayList and LinkedList. Are you sure you didn't mean to use just List, the interface?

This code works:

List<String> listOfStrings = new ArrayList<String>();

listOfStrings.add("one");
listOfStrings.add("two");

Gson gson = new Gson();
String json = gson.toJson(listOfStrings);

System.out.println(json);

Type type = new TypeToken<Collection<String>>(){}.getType();

List<String> fromJson = gson.fromJson(json, type);

System.out.println(fromJson);

Update: I changed your class to this, so I don't have to mess around with other classes:

class IndicesAndWeightsParams {

public List<Integer> indicesParams;
public List<String> weightsParams;

public IndicesAndWeightsParams() {
indicesParams = new ArrayList<Integer>();
weightsParams = new ArrayList<String>();
}
public IndicesAndWeightsParams(ArrayList<Integer> indicesParams, ArrayList<String> weightsParams) {
this.indicesParams = indicesParams;
this.weightsParams = weightsParams;
}
}

And using this code, everything works for me:

ArrayList<Integer> indices = new ArrayList<Integer>();
ArrayList<String> weights = new ArrayList<String>();

indices.add(2);
indices.add(5);

weights.add("fifty");
weights.add("twenty");

IndicesAndWeightsParams iaw = new IndicesAndWeightsParams(indices, weights);

Gson gson = new Gson();
String string = gson.toJson(iaw);

System.out.println(string);

IndicesAndWeightsParams fromJson = gson.fromJson(string, IndicesAndWeightsParams.class);

System.out.println(fromJson.indicesParams);
System.out.println(fromJson.weightsParams);

Gson toJson() method problem with HashMapString,Object

The way you have declared it, map is not a HashMap, but an anonymous class. Gson is not designed to handle anonymous and inner classes.

You can check this issue, which asks about serialization of anonymous class, but it's closed, so probably there are no plans to add support for this. As you can see in the discussion, possible workaround is providing the type.

System.out.println(new Gson().toJson(map, new TypeToken<HashMap<String, Object>>(){}.getType()));

Another related discussion.

How to serialize ArrayList of Pair using gson

I got it. The problem was that I was using kotlin's Pair class. As soon as I defined my own simple Pair class, everything worked out correctly.



Related Topics



Leave a reply



Submit