21

I am trying to parse json to java.

I have the following string that is valid json according to jsonlint.com

private final static String LOC_JSON = 
         "["
        +"{"
        +"  \"lat1\": 39.737567,"
        +"  \"lat2\": 32.7801399,"
        +"  \"long1\": -104.98471790000002,"
        +"  \"long2\": -96.80045109999998"
        +"},"
        +"  ["
        +"      {"
        +"          \"lat\": {"
        +"              \"b\": 38.88368709500021,"
        +"              \"d\": 40.620468491667026"
        +"          },"
        +"          \"long\": {"
        +"          \"b\": -105.75306170749764,"
        +"          \"d\": -104.675854661387"
        +"          }"
        +"      }"
        +"  ]"
        +"]";

I am trying to parse it into an object and I get the following error. "Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2"

            Gson gson = new Gson();
        BoxSearch b = gson.fromJson( LOC_JSON, BoxSearch.class ); 

BoxSearch consists of this.

private Number lat1;
private Number lat2;
private Number long1;
private Number long2;
private Boxes[] boxes;

Boxes is a Latitude object and a Longitude object which are both defined identical.

private String b;
private String d;

I can parse the higher level attributes (lat1,lat2,long1 and long2) into a more simple BoxSearch object that only has those 4 attributes. The trouble comes when the json and the object are more complex. Is it even possible to do what I am trying?

I hope I have provided enough information to get some help. I would be happy to provide more info or even a test project if need be. I am running this as a junit test.

Thanks.

user2415153
  • 223
  • 1
  • 2
  • 4
  • 3
    possible duplicate of [GSON throwing "Expected BEGIN\_OBJECT but was BEGIN\_ARRAY"?](http://stackoverflow.com/questions/9598707/gson-throwing-expected-begin-object-but-was-begin-array) - your JSON is an array, not an object. You are going to have a problem though because it's an array containing different types of objects (an object and an array) which you can not deal with without writing a custom deserializer – Brian Roach May 23 '13 at 20:21
  • @BrianRoach this is more like an answer ;) –  May 23 '13 at 20:26
  • @RC. Yeah ... Hmm. I think maybe I'll move it, the old Q answers why he's getting the error, but the resolution to his case is different – Brian Roach May 23 '13 at 20:29
  • I did go through the possible duplicate but that object is simple as opposed to complex. Is there a better way to organize the json string? My UI is putting it together (based on google maps) but I can manipulate it. I guess I will try more simple/flatter object. Or is writing a custom deserializer the way to go? – user2415153 May 23 '13 at 20:45
  • @user2415153 - see my extended answer below. If you're the one generating the JSON, then yes - redoing that so it's an object rather than an array will make your life much easier. Let me expand on that a bit in my answer; editing. – Brian Roach May 23 '13 at 20:47
  • @user2415153 see final editing of my answer. – Brian Roach May 23 '13 at 21:01

2 Answers2

33
Gson gson = new Gson();
gson.fromJson(jsonStr,YourClass.class);

very easy.

David Wang
  • 934
  • 1
  • 12
  • 16
  • it help me to convert a json object that have a list inside. I convert the json string to Object.class – Ashkan Jan 12 '17 at 06:28
24

The reason for the error is that your JSON at the top level is an array, not an object. That is covered by GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?.

However, the solution there won't work for your JSON because you have an array of mixed types (an object and an array) rather than an array of a single type of object. For that you're going to have to write a custom deserializer (See The section of the Gson user's guide that covers this) or use Gson's JsonParser class directly and extract the data from the parse tree.

Edit from comments above:

If you're the one creating the JSON, it looks like what you want is an array of BoxSearch objects?

Based on your Java BoxSearch class, you'd need JSON structured like:

[
    {
        "lat1" : 39.737567,
        "lat2" : 32.7801399,
        "long1" : -104.98471790000002,
        "long2" : -96.80045109999998,
        "boxes" : [ 
                    {
                      "lat": {
                          "b": 38.88368709500021,
                          "d": 40.620468491667026
                      },
                      "long": {
                          "b": -105.75306170749764,
                          "d": -104.675854661387
                      }
                    }
                  ]
    }
]

However, the way you have Boxes class defined won't work for that. (Did you mean to have an array of them?). As-is it would need to look like:

class Boxes {
    Box lat;
    @SerializedName("long")
    Box lon;
}

class Box {
   String b;
   String d;
}

Now you have an array containing one type of object (BoxSearch) which you could deserialize with:

Type collectionType = new TypeToken<Collection<BoxSearch>>(){}.getType();
Collection<BoxSearch> boxSearchCollection = gson.fromJson(json, collectionType);

If you really don't need an array of these, get rid of the outer array and simply do:

gson.fromJson(json, BoxSearch.class);
Community
  • 1
  • 1
Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • Thank you very much Brian, that slight tweak to the json and all is well. I would vote this answer up but I have no "street cred". The code works like a champ. In case people copy and paste this answer, Box long; needs to be renamed :-) – user2415153 May 24 '13 at 13:50
  • Oh and yes I needed the array. Thanks again. – user2415153 May 24 '13 at 13:54
  • @user2415153 I changed the code so it'll work with `"long"` in the JSON - see the answer now :) I didn't notice that, sorry. As for upvoting - you can accept my answer ;) and glad I could help! – Brian Roach May 24 '13 at 14:10
  • Fancy solution! I just renamed the variables to the full words. Accepting as answered! Thanks again! – user2415153 May 24 '13 at 15:09