Question

I'm trying to deserialize JSON from Reddit that you can obtain by appending .json to the url. An example would be:

http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top

However, I am getting the error message:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 9765

At line 1 column 9765 in the json there is the following code: "replies": "", whereas normally this would contain an object like this: replies: { kind: "Listing", data: {} },

Does this mean that the json is a String when there is no data, but an object otherwise? How can I deserialize with gson properly if this is the case? I've included my classes below. I still need to figure out how to handle the json starting off with an array of basically two different objects (the first listing in the json is describing the link, while the second listing is describing the comments), but I'll cross that bridge when I get there. Thanks in advance if anyone can shed some light on this issue.

Main Class

public static void main(String[] args)
{
    ArrayList<CommentsResults> commentsResults = new ArrayList<CommentsResults>();
    String commentsURL = "http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top";
    URL url = null;
    try
    {
        url = new URL(commentsURL);
    } catch (MalformedURLException ex)
    {
        System.out.println(ex.getMessage());
    }

    try
    {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
        String jsonText = readAll(bufferedReader);
        Gson gson = new GsonBuilder().create();
        commentsResults = gson.fromJson(jsonText, new TypeToken<ArrayList<CommentsResults>>(){}.getType());
    } catch (IOException ex)
    {
        System.out.println(ex.getMessage());
    }
}
private static String readAll(Reader reader) throws IOException
{
    StringBuilder stringBuilder = new StringBuilder();
    int cp;
    while ((cp = reader.read()) != -1)
    {
        stringBuilder.append((char) cp);
    }
    return stringBuilder.toString();
}

CommentsResults Class

public class CommentsResults {

private String kind;
private CommentsData data;    

public CommentsResults()
{
}

public CommentsResults(String kind, CommentsData data)
{
    this.kind = kind;
    this.data = data;
}

public String getKind()
{
    return kind;
}

public CommentsData getData()
{
    return data;
}

public void setKind(String kind)
{
    this.kind = kind;
}

public void setData(CommentsData data)
{
    this.data = data;
}    

}

CommentsData Class

private String modhash;
private List <CommentsChild> children; 

public CommentsData()
{
}

public CommentsData(String modhash, List<CommentsChild> children)
{
    this.modhash = modhash;
    this.children = children;
}

public String getModhash()
{
    return modhash;
}

public List<CommentsChild> getChildren()
{
    return children;
}

public void setModhash(String modhash)
{
    this.modhash = modhash;
}

public void setChildren(List<CommentsChild> children)
{
    this.children = children;
}       

CommentsChild Class

private String kind;
private Comment data;

public CommentsChild()
{
}

public CommentsChild(String kind, Comment comment)
{
    this.kind = kind;
    this.data = comment;
}

public String getKind()
{
    return kind;
}

public Comment getComment()
{
    return data;
}

public void setKind(String kind)
{
    this.kind = kind;
}

public void setComment(Comment comment)
{
    this.data = comment;
} 

Comment Class

public class Comment {

private CommentsResults replies;

private String id;

private int gilded;

private String author;

private String parent_id;

private String body;

private int downs;

private String link_id;

private boolean score_hidden;

private int created_utc;

private String distinguished;

public Comment()
{
}

public Comment(CommentsResults replies, String id, int gilded, String author, String parent_id, String body, int downs, String link_id, boolean score_hidden, int created_utc, String distinguished)
{
    this.replies = replies;
    this.id = id;
    this.gilded = gilded;
    this.author = author;
    this.parent_id = parent_id;
    this.body = body;
    this.downs = downs;
    this.link_id = link_id;
    this.score_hidden = score_hidden;
    this.created_utc = created_utc;
    this.distinguished = distinguished;
}

public CommentsResults getReplies()
{
    return replies;
}

public String getId()
{
    return id;
}

public int getGilded()
{
    return gilded;
}

public String getAuthor()
{
    return author;
}

public String getParent_id()
{
    return parent_id;
}

public String getBody()
{
    return body;
}

public int getDowns()
{
    return downs;
}

public String getLink_id()
{
    return link_id;
}

public boolean isScore_hidden()
{
    return score_hidden;
}

public int getCreated_utc()
{
    return created_utc;
}

public String getDistinguished()
{
    return distinguished;
}

public void setReplies(CommentsResults replies)
{
    this.replies = replies;
}

public void setId(String id)
{
    this.id = id;
}

public void setGilded(int gilded)
{
    this.gilded = gilded;
}

public void setAuthor(String author)
{
    this.author = author;
}

public void setParent_id(String parent_id)
{
    this.parent_id = parent_id;
}

public void setBody(String body)
{
    this.body = body;
}

public void setDowns(int downs)
{
    this.downs = downs;
}

public void setLink_id(String link_id)
{
    this.link_id = link_id;
}

public void setScore_hidden(boolean score_hidden)
{
    this.score_hidden = score_hidden;
}

public void setCreated_utc(int created_utc)
{
    this.created_utc = created_utc;
}

public void setDistinguished(String distinguished)
{
    this.distinguished = distinguished;
}    
}
Était-ce utile?

La solution

So in the off chance this helps somebody (which seems dubious at this point) I decided to parse the Json manually using recursion. Here's how I did it:

public static void getCommentsOnLink()
{               
    String commentsURL= "http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top";
    URL url = null;
    try
    {
        url = new URL(commentsURL);
    } catch (MalformedURLException ex)
    {
        System.out.println(ex.getMessage());
    }
    String JsonText = readCommentJsonFromURL(url);

    RedditCommentResults redditCommentResults = getCommentResults(JsonText);
}

private static String readCommentJsonFromURL(URL url)
{
    String JSONText = null;
    try
    {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
        JSONText = readAll(bufferedReader);
    } catch (IOException ex)
    {
        System.out.println(ex.getMessage());
    }
    return JSONText;
}

private static String readAll(Reader reader) throws IOException
{
    StringBuilder stringBuilder = new StringBuilder();
    int cp;
    while ((cp = reader.read()) != -1)
    {
        stringBuilder.append((char) cp);
    }
    return stringBuilder.toString();
}    

private static RedditCommentResults getCommentResults(String JsonText)
{
    JsonParser parser = new JsonParser();
    JsonArray completeJson = (JsonArray) parser.parse(JsonText);

    //get link and comment object from the array containing an object for each
    JsonObject linkParentJson = (JsonObject) completeJson.get(0);
    JsonObject commentParentJson = (JsonObject) completeJson.get(1);

    //use automatic deserializer for redditLink
    JsonObject linkListingDataJson = linkParentJson.getAsJsonObject("data");
    JsonObject linkChildrenJson = linkListingDataJson.getAsJsonArray("children").get(0).getAsJsonObject();
    JsonObject linkDataJson = linkChildrenJson.getAsJsonObject("data");
    Link commentLink = gson.fromJson(linkDataJson, Link.class);
    RedditLink redditCommentLink = new RedditLink(commentLink);

    //parse comments manually
    JsonObject commentDataJson = commentParentJson.getAsJsonObject("data");
    JsonArray commentChildrenJson = commentDataJson.getAsJsonArray("children");

    //get all of the comments from the JsonArray
    ArrayList<RedditComment> redditComments = getNestedComments(commentChildrenJson);

    RedditCommentResults redditCommentResults = new RedditCommentResults(redditComments, redditCommentLink);
    return redditCommentResults;
}

private static ArrayList<RedditComment> getNestedComments(JsonArray commentWrapperJsonArray)
{
    ArrayList<RedditComment> redditComments = new ArrayList();
    for (JsonElement commentWrapperJson : commentWrapperJsonArray)
    {
        //cast Element to Object so we can search for the primitive "kind".  Finally we get it as a String
        String kind = commentWrapperJson.getAsJsonObject().getAsJsonPrimitive("kind").getAsString();

        //if the comment is of type t1 meaning it is a comment and not a "more" (a "more" is a comment which 
        //hasn't been loaded yet because it does not have a great deal of upvotes relative to other comments)
        if (kind.equals("t1"))
        {
            JsonObject commentJson = commentWrapperJson.getAsJsonObject().getAsJsonObject("data");
            Comment comment = gson.fromJson(commentJson, Comment.class);
            RedditComment redditComment = new RedditComment(comment);

            JsonElement repliesJson = commentJson.get("replies");

            //if the reply is not equal to an empty String (i.e. if there is at least one reply)
            if (!repliesJson.isJsonPrimitive())
            {
                JsonObject dataJson = repliesJson.getAsJsonObject().getAsJsonObject("data");
                JsonArray childrenJson = dataJson.getAsJsonArray("children");
                ArrayList<RedditComment> nestedComments = getNestedComments(childrenJson);
                redditComment.setReplies(nestedComments);
            }
            redditComments.add(redditComment);
        }
    }
    return redditComments;
}

Autres conseils

You have to remove the private CommentsResults replies; from Comment Class and compose replies in CommentsChild class. According to Json fomate you model is

CommentResult -
      CommentsData --
            List <CommentsChild> children---
                   CommentsResults replies
                        recursion/ repeation of comment result

public class CommentsChild {
    private String kind;
    private Comment data;
    // 
    private CommentsResults replies;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top