2

I have a small test application I'm writing in Java to parse some JSON from the Reddit API. Some sample JSON I'm looking to parse would be like this:

[
{
    "kind": "Listing",
    "data": {
        "modhash": "1jq62oyvwe15aaba7eb18b0b4363b567a00750766351e03dcc",
        "children": [
            {
                "kind": "t3",
                "data": {
                    "domain": "businessinsider.com",
                    "media_embed": {},
                    "levenshtein": null,
                    "subreddit": "Android",
                    "selftext_html": null,
                    "selftext": "",
                    "likes": null,
                    "saved": false,
                    "id": "n17u2",
                    "clicked": false,
                    "title": "CONFESSION OF A NON-APPLE-FANBOY: Even If The Samsung Galaxy Nexus Is Better, I'm Still Buying An iPhone",
                    "media": null,
                    "score": 0,
                    "over_18": false,
                    "hidden": false,
                    "thumbnail": "http://e.thumbs.redditmedia.com/sL0dCwGAvWqnY_sd.jpg",
                    "subreddit_id": "t5_2qlqh",
                    "author_flair_css_class": null,
                    "downs": 2,
                    "is_self": false,
                    "permalink": "/r/Android/comments/n17u2/confession_of_a_nonapplefanboy_even_if_the/",
                    "name": "t3_n17u2",
                    "created": 1323127132,
                    "url": "http://www.businessinsider.com/apple-iphone-versus-samsung-galaxy-nexus-2011-12",
                    "author_flair_text": null,
                    "author": "FormulaT",
                    "created_utc": 1323101932,
                    "num_comments": 0,
                    "ups": 1
                }
            }
        ],
        "after": null,
        "before": null
    }
},
{
    "kind": "Listing",
    "data": {
        "modhash": "1jq62oyvwe15aaba7eb18b0b4363b567a00750766351e03dcc",
        "children": [],
        "after": null,
        "before": null
    }
}
]

What I'm trying to accomplish is to get just a few values out of this JSON, e.g. the title and the author. I'm using Jackson to handle the JSON, and the code I'm using looks like this:

URLConnection conn = redditURL.openConnection();
BufferedReader buf = new BufferedReader(new InputStreamReader(conn.getInputStream()));

ObjectMapper mapper = new ObjectMapper();
RedditComment comment = mapper.readValue(buf, RedditComment.class);
Iterator itr = comment.getData().getChildren().listIterator();

I created the RedditComment and other needed classes using the JSONGen website (http://jsongen.byingtondesign.com/). However, when parsing the JSON from the BufferedReader, Jackson throws this exception:

org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.test.RedditAPI.RedditComment out of START_ARRAY token
at [Source: java.io.BufferedReader@3ebfbbe3; line: 1, column: 1]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:212)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromArray(BeanDeserializer.java:869)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:597)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2723)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1877)
at com.test.RedditAPI.main.returnRedditComment(Main.java:17)

Does anyone have any ideas? I've been scratching my head for a few hours now.

EDIT: Thanks to @Chin Boon and @Chris, I came up with the following (after switching to GSON):

Gson gson = new Gson();
List<RedditComment> comment = gson.fromJson(buf, new TypeToken<List<RedditComment>>() {}.getType());
List<RedditChildren> children = comment.get(1).getData().getChildren();
System.out.println(children.get(1).getData().getAuthor());

but that throws the following exception:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.test.RedditAPI.RedditChildren

Apologies if I'm being a bother, I've looked around the API and there isn't any reference of LinkedHashMaps, so I don't know why it's popping up here.

Ryan Morrison
  • 593
  • 2
  • 8
  • 18
  • 1
    Just a wild guess, but I think you have to remove the _normal_ brackets (`[` and `]`) around the curly brackets in your input. Or! You have to tell Jackson to treat your input as a JSON array instead of a JSON object. (JSON arrays, as far as I know are in brackets, while objects are in curly brackets. See the [related literature](http://json.org/).) – Kohányi Róbert Dec 05 '11 at 16:47
  • possible duplicate of http://stackoverflow.com/q/4392326/922954 ? – aishwarya Dec 05 '11 at 16:52

2 Answers2

5

The problem is that the response is an array of entries. Try:

List<RedditComment> comment = mapper.readValue(buf,new TypeReference<List<RedditComment>>(){});
Chris
  • 22,923
  • 4
  • 56
  • 50
1

if you have not already invested too much time into Jackson, may i recommend you looking at GSON, here is a tutorial that should have you started.

Google GSON API maps your JSON string into a domain object.

http://java.sg/parsing-a-json-string-into-an-object-with-gson-easily/

Also, you can use a JSON parser to see your JSON.

Oh Chin Boon
  • 23,028
  • 51
  • 143
  • 215
  • Hi Milk, comment.get(1).getData().getChildren() points to nothing, there is insufficient data at 1 to get you to children, you should put the iterator to 0 and try, nonetheless i doubt that is the issue. Does the exception stacktrace point the error to gson.fromJson or the subsequent lines you are trying to traverse the GSON object? – Oh Chin Boon Dec 05 '11 at 22:48
  • The stack trace pointed to gson.fromJson, however I've worked out my issue - I switched to the json.org libraries and was able to extract the data I needed with relative ease. Thanks for the assistance anyway! – Ryan Morrison Dec 06 '11 at 02:38
  • Hey great to hear that buddy! What library were you using previously? – Oh Chin Boon Dec 06 '11 at 02:40
  • There is nothing about the original problem that suggests switching APIs from Jackson to Gson is necessary, or otherwise makes for a simpler solution. Both Jackson and Gson offer very similar possible solutions. – Programmer Bruce Dec 10 '11 at 17:08