Gson and Deserializing an Array of Objects with Arrays in It

Gson and deserializing an array of objects with arrays in it

The example Java data structure in the original question does not match the description of the JSON structure in the comment.

The JSON is described as

"an array of {object with an array of {object}}".

In terms of the types described in the question, the JSON translated into a Java data structure that would match the JSON structure for easy deserialization with Gson is

"an array of {TypeDTO object with an array of {ItemDTO object}}".

But the Java data structure provided in the question is not this. Instead it's

"an array of {TypeDTO object with an array of an array of {ItemDTO object}}".

A two-dimensional array != a single-dimensional array.

This first example demonstrates using Gson to simply deserialize and serialize a JSON structure that is "an array of {object with an array of {object}}".

input.json Contents:

[
{
"id":1,
"name":"name1",
"items":
[
{"id":2,"name":"name2","valid":true},
{"id":3,"name":"name3","valid":false},
{"id":4,"name":"name4","valid":true}
]
},
{
"id":5,
"name":"name5",
"items":
[
{"id":6,"name":"name6","valid":true},
{"id":7,"name":"name7","valid":false}
]
},
{
"id":8,
"name":"name8",
"items":
[
{"id":9,"name":"name9","valid":true},
{"id":10,"name":"name10","valid":false},
{"id":11,"name":"name11","valid":false},
{"id":12,"name":"name12","valid":true}
]
}
]

Foo.java:

import java.io.FileReader;
import java.util.ArrayList;

import com.google.gson.Gson;

public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
TypeDTO[] myTypes = gson.fromJson(new FileReader("input.json"), TypeDTO[].class);
System.out.println(gson.toJson(myTypes));
}
}

class TypeDTO
{
int id;
String name;
ArrayList<ItemDTO> items;
}

class ItemDTO
{
int id;
String name;
Boolean valid;
}

This second example uses instead a JSON structure that is actually "an array of {TypeDTO object with an array of an array of {ItemDTO object}}" to match the originally provided Java data structure.

input.json Contents:

[
{
"id":1,
"name":"name1",
"items":
[
[
{"id":2,"name":"name2","valid":true},
{"id":3,"name":"name3","valid":false}
],
[
{"id":4,"name":"name4","valid":true}
]
]
},
{
"id":5,
"name":"name5",
"items":
[
[
{"id":6,"name":"name6","valid":true}
],
[
{"id":7,"name":"name7","valid":false}
]
]
},
{
"id":8,
"name":"name8",
"items":
[
[
{"id":9,"name":"name9","valid":true},
{"id":10,"name":"name10","valid":false}
],
[
{"id":11,"name":"name11","valid":false},
{"id":12,"name":"name12","valid":true}
]
]
}
]

Foo.java:

import java.io.FileReader;
import java.util.ArrayList;

import com.google.gson.Gson;

public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
TypeDTO[] myTypes = gson.fromJson(new FileReader("input.json"), TypeDTO[].class);
System.out.println(gson.toJson(myTypes));
}
}

class TypeDTO
{
int id;
String name;
ArrayList<ItemDTO> items[];
}

class ItemDTO
{
int id;
String name;
Boolean valid;
}

Regarding the remaining two questions:

is Gson extremely fast?

Not compared to other deserialization/serialization APIs. Gson has traditionally been amongst the slowest. The current and next releases of Gson reportedly include significant performance improvements, though I haven't looked for the latest performance test data to support those claims.

That said, if Gson is fast enough for your needs, then since it makes JSON deserialization so easy, it probably makes sense to use it. If better performance is required, then Jackson might be a better choice to use. It offers much (maybe even all) of the conveniences of Gson.

Or am I better to stick with what I've got working already?

I wouldn't. I would most always rather have one simple line of code like

TypeDTO[] myTypes = gson.fromJson(new FileReader("input.json"), TypeDTO[].class);

...to easily deserialize into a complex data structure, than the thirty lines of code that would otherwise be needed to map the pieces together one component at a time.

How to deserialize array of arrays with GSON

Since it's an array of array of mixed types, aka a list of list of mixed types, use:

... = new TypeToken<List<List<Object>>>() {}.getType();
List<List<Object>> enums = ...

Gson will not map an array to a POJO. For what you want, the JSON should have been:

[{"id":1, "name":"a"}, {"id":2, "name":"b"}]

As is, converting the List<List<Object>> into a List<A> is up to you.

How to deserialize a JSON array of objects using Gson library?

To deserialize a JSONArray you need to use TypeToken. You can read more about it from GSON user guide. Example code:

@Test
public void JSON() {
Gson gson = new Gson();
Type listType = new TypeToken<List<MyObject>>(){}.getType();
// In this test code i just shove the JSON here as string.
List<Asd> asd = gson.fromJson("[{'name':\"test1\"}, {'name':\"test2\"}]", listType);
}

If you have a JSONArray then you can use

...
JSONArray jsonArray = ...
gson.fromJson(jsonArray.toString(), listType);
...

How do I deserialize a nested JSON array using GSON?

You can not skip root JSON object. The simplest solution in this case is - create root POJO:

class Response {
@SerializedName("value")
private List<Customer> customers;

// getters, setters
}

And you can use it as below:

return gson.fromJson(json, Response.class).getCustomers();

Deserializing json array using gson?

Changing the return type of deserialize() from Category to ArrayList<Category> solved the issue. Rest of the code is correct.

Gson: deserializing arrays where elements are not of same type

There is no Java type that is compatible with the json array you are trying to deserialize. You should use JsonParser to get a JsonObject and then process that JsonObject manually.

JsonParser p = new JsonParser();
JsonObject jsonObject = (JsonObject)p.parse(yourJsonString);

You can then process your jsonObject like this:

    List<Foo> foos = new ArrayList<Foo>();
JsonArray response = jsonObject.getAsJsonArray("response");
for (int i = 0; i < response.size(); i++) {
JsonElement el = response.get(i);
if (el.isJsonObject()) {
Foo f = new Foo();
JsonObject o = el.getAsJsonObject();
int id = o.getAsJsonPrimitive("id").getAsInt();
String name = o.getAsJsonPrimitive("name").getAsString();
f.Id = id;
f.Name = name;
foos.add(f);
}
}

Alternatively you could process the response JsonArray like this:

    List<Foo> foos = new ArrayList<Foo>();
JsonArray response = jsonObject.getAsJsonArray("response");
for (int i = 0; i < response.size(); i++) {
JsonElement el = response.get(i);
if (el.isJsonObject()) {
JsonObject o = el.getAsJsonObject();
Foo f = gson.fromJson(o, Foo.class);
foos.add(f);
}
}

But you need to make sure the Foo class member names match the json property names. Yours do not because of capitalization. i.e. you need to change your Foo class to be like this:

class Foo {
int id;
String name;
}


Related Topics



Leave a reply



Submit