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
How to Set Java Max Heap Size for Running from a Jar File
Java Threads and Number of Cores
Collection Interface VS Arrays
When Not to Use the Static Keyword in Java
Accessing Constructor of an Anonymous Class
How to Get Method Parameter Names in Java 8 Using Reflection
JPA - Returning an Auto Generated Id After Persist()
Change Database Schema Used by Spring Boot
Java Conventions: Use Getters/Setters Within the Class
Difference Between Openjdk and Adoptium/Adoptopenjdk
The Most Sophisticated Way for Creating Comma-Separated Strings from a Collection/Array/List
Cleanest Way to Toggle a Boolean Variable in Java
Unsatisfieddependencyexception: Error Creating Bean with Name
How to Disable the Default Console Handler, While Using the Java Logging API
How to Convert a Binary String to a Base 10 Integer in Java