75

I am trying to use Gson to deserialize a json string returned from my webservice

The structure would be returned as TypeDTO[].

where TypeDTO is like

int id;
String name;
ArrayList<ItemDTO> items[] 

and ItemDTO is like

int id;
String name;
Boolean valid;

When I call the code as follows

Gson gson = new Gson();
TypeDTO[] mytypes = (TypeDTO[]) gson.fromJson(reply, TypeDTO[].class);

Everything inside the objects is null

However, If I use the

JSONArray and JSONObject to pull them out piece by piece from the org.json jars, it works fine and the fields are populated accordingly.

Any ideas as to what I'm doing wrong? is Gson extremely fast? Or am I better to stick with what I've got working already?

Thanks, David

ColinD
  • 108,630
  • 30
  • 201
  • 202
DavieDave
  • 1,394
  • 2
  • 18
  • 35
  • You need to give more information. What is the format of the JSON you're receiving? Why do you have an array of `ArrayList` in your `TypeDTO`? Gson handles this sort of thing fine. – ColinD Sep 21 '10 at 20:13
  • I thought I gave a clear picture of the JSON. Top level is a list of objects. Each object has multiple kv pairs, one of them being another list of objects with more kv pairs. – DavieDave Sep 23 '10 at 02:49
  • @daviedave : I think programmer-bruce's answer deserves Marked Accepted – Sumit Ramteke Feb 25 '14 at 09:31

2 Answers2

134

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.

Dherik
  • 17,757
  • 11
  • 115
  • 164
Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
  • Thanks for your solution, after three hours of trying in vain, your method was the best I found. – Awemo May 29 '12 at 13:08
  • 9
    @Programmer Bruce +1 for saying "rather have one simple line of code". The power of GSON is not how fast it parses, but how fast it is to write and maintain the code required for a large number of production cases. And when you need to optimise, GSON's streaming model does provide great performance increases. – Richard Le Mesurier Aug 28 '12 at 07:44
2

Use your bean class like this, if your JSON data starts with an an array object. it helps you.

Users[] bean = gson.fromJson(response,Users[].class);

Users is my bean class.

Response is my JSON data.

Sunil
  • 3,404
  • 10
  • 23
  • 31