1

So I have been able to get JSON objects for a few things, however this object is quite a bit more complex.

I'm trying to get comments from Reddit. Here is the method I use:

    public async Task<List<string>> GetComments(string currentSubreddit, string topicID)
    {
        string commentUrl = "http://www.reddit.com/r/" + currentSubreddit  + "/comments/" + topicID + "/.json";
        List<Comments> commentList = new List<Comments>();
        string jsonText = await wc.GetJsonText(commentUrl);

        Comments.RootObject deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Comments.RootObject>(jsonText);

        List<string> commentListTest = new List<string>();
        //List<string> commentListTest = deserializeObject.data.children[0].data.children;
        return commentListTest;

    }

This is the GetJsonText method:

    public async Task<string> GetJsonText(string url)
    {
        var request = WebRequest.Create(url);
        string text;
        request.ContentType = "application/json; charset=utf-8";
        var response = (HttpWebResponse)await request.GetResponseAsync();

        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            text = sr.ReadToEnd();
        }

        return text;
    }

And here is a link to the Object: http://pastebin.com/WQ8XXGNA And a link to the jsonText: http://pastebin.com/7Kh6cA9a

The error returned says this:

An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in mscorlib.dll but was not handled in user code

Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JuicyReddit.Comments+RootObject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

I'd appreciate if anybody could help me with figuring out whats wrong with this. Thanks

Ayohaych
  • 5,099
  • 7
  • 29
  • 51
  • 1
    From where do u get this json data ? Thinking the json string u posted is not valid. – Jim Jan 10 '14 at 01:35
  • @Jim I get this url and use it in GetJsonText www.reddit.com/r/AskReddit/comments/1ut6xc/.json – Ayohaych Jan 10 '14 at 02:07
  • 1
    The additional error is explained here http://stackoverflow.com/questions/17762032/cannot-deserialize-the-current-json-array-e-g-1-2-3-into-type – Jim Jan 10 '14 at 03:01
  • @Jim Would you have any idea how to do it in my situation using Newtonsoft? Still not sure how to fix it. – Ayohaych Jan 10 '14 at 03:27

2 Answers2

1

It's not ideal (and not completely an answer but more of a work around) but I created models that mock the reddit response json to make deserialization super easy. I use JsonProperty attributes on my model properties to pretty up the models a bit.

Here are the models

And since my models directly mock the json I can just use json.net's generic deserialize method.

Neil Smith
  • 2,565
  • 1
  • 15
  • 18
  • How would I do it using the Newtonsoft plugin. Sort of confused as to how its all working S: – Ayohaych Jan 10 '14 at 03:36
  • 1
    Let's say I executed a get to reddit.com/r/all.json, Reddit gives you a 'Listing'. I mock the listing json with ListingModel. To get a strongly typed ListingModel, all I have to do is: var listing = JsonConvert.DeserializeObject(response) where response is the json. Since ListingModel and its children mock the json returned, it just matches the property names in the json with my model. Check out the test console project in that repo if you want to see how it's used. – Neil Smith Jan 10 '14 at 14:34
1

There are a few problems with your code actually

 public async Task<List<string>> GetComments(string currentSubreddit, string topicID)

You don't need to return a list of string here, u need to return a full object

First rename RootObject in the model to an appropriate name such as "CommentsObject"

So set up your class like so and name it CommentsObject.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YOURNAMESPACE.Comments
{
    public class MediaEmbed
    {
    }

    public class SecureMediaEmbed
    {
    }

    public class Data4
    {
        public int count { get; set; }
        public string parent_id { get; set; }
        public List<string> children { get; set; }
        public string name { get; set; }
        public string id { get; set; }
        public string subreddit_id { get; set; }
        public object banned_by { get; set; }
        public string subreddit { get; set; }
        public object likes { get; set; }
        public object replies { get; set; }
        public bool? saved { get; set; }
        public int? gilded { get; set; }
        public string author { get; set; }
        public object approved_by { get; set; }
        public string body { get; set; }
        public object edited { get; set; }
        public object author_flair_css_class { get; set; }
        public int? downs { get; set; }
        public string body_html { get; set; }
        public string link_id { get; set; }
        public bool? score_hidden { get; set; }
        public double? created { get; set; }
        public object author_flair_text { get; set; }
        public double? created_utc { get; set; }
        public object distinguished { get; set; }
        public object num_reports { get; set; }
        public int? ups { get; set; }
    }

    public class Child2
    {
        public string kind { get; set; }
        public Data4 data { get; set; }
    }

    public class Data3
    {
        public string modhash { get; set; }
        public List<Child2> children { get; set; }
        public object after { get; set; }
        public object before { get; set; }
    }

    public class Replies
    {
        public string kind { get; set; }
        public Data3 data { get; set; }
    }

    public class Data2
    {
        public string domain { get; set; }
        public object banned_by { get; set; }
        public MediaEmbed media_embed { get; set; }
        public string subreddit { get; set; }
        public object selftext_html { get; set; }
        public string selftext { get; set; }
        public object likes { get; set; }
        public object secure_media { get; set; }
        public object link_flair_text { get; set; }
        public string id { get; set; }
        public SecureMediaEmbed secure_media_embed { get; set; }
        public bool clicked { get; set; }
        public bool stickied { get; set; }
        public string author { get; set; }
        public object media { get; set; }
        public int score { get; set; }
        public object approved_by { get; set; }
        public bool over_18 { get; set; }
        public bool hidden { get; set; }
        public string thumbnail { get; set; }
        public string subreddit_id { get; set; }
        public object edited { get; set; }
        public object link_flair_css_class { get; set; }
        public object author_flair_css_class { get; set; }
        public int downs { get; set; }
        public bool saved { get; set; }
        public bool is_self { get; set; }
        public string permalink { get; set; }
        public string name { get; set; }
        public double created { get; set; }
        public string url { get; set; }
        public object author_flair_text { get; set; }
        public string title { get; set; }
        public double created_utc { get; set; }
        public int ups { get; set; }
        public int num_comments { get; set; }
        public bool visited { get; set; }
        public object num_reports { get; set; }
        public object distinguished { get; set; }
        public Replies replies { get; set; }
        public int? gilded { get; set; }
        public string parent_id { get; set; }
        public string body { get; set; }
        public string body_html { get; set; }
        public string link_id { get; set; }
        public bool? score_hidden { get; set; }
        public int? count { get; set; }
        public List<string> children { get; set; }
    }

    public class Child
    {
        public string kind { get; set; }
        public Data2 data { get; set; }
    }

    public class Data
    {
        public string modhash { get; set; }
        public List<Child> children { get; set; }
        public object after { get; set; }
        public object before { get; set; }
    }

    public class CommentsObject
    {
        public string kind { get; set; }
        public Data data { get; set; }
    }
}

Make your namespace correct!

Then handle the request and deserialise into a list of commentobjects: (u can use the webclient instead of httpclient if you want, this is just an example)

    private HttpClient client;

    public async Task<List<CommentsObject>> GetComments()
    {
        client = new HttpClient();
        var response = await client.GetAsync("http://www.reddit.com/r/AskReddit/comments/1ut6xc.json");
        if (response.IsSuccessStatusCode)
        {
            string json = await response.Content.ReadAsStringAsync();
            List<CommentsObject> comments = await JsonConvert.DeserializeObjectAsync<List<CommentsObject>>(json);
            return comments;
        }
        else
        {
            throw new Exception("Errorhandling message");
        }
    }
Jim
  • 2,974
  • 2
  • 19
  • 29
  • thanks for the indepth response really appreciate it. One error im coming with is with the namespace. When I try to do for the GetComments() method it says the namespace is being used like a type – Ayohaych Jan 10 '14 at 14:53
  • 1
    Getcomments() is a method in a service class or on for example your form backendcode – Jim Jan 10 '14 at 15:01
  • I understand. This is what the type of my method looks like: public async Task> GetComments(string url) Should that work? Because I'm not getting comments back from it. Would you mind starting a chat just for some quick help? – Ayohaych Jan 10 '14 at 15:12
  • actually I think i have it working. What would be the best way to iterate through this and add the comments to a list view? because when i get the list back theres always 2 elements in it and just sure what i should do – Ayohaych Jan 10 '14 at 15:34
  • 1
    That would be a different topic i suppose :), but yes in this case u get 2 arrays u need to dig into and iterate to get the comments – Jim Jan 10 '14 at 15:38