0

I am trying to query the Reddit API and looping over answers for a thread to get the answer I want. However, when I query the api (https://www.reddit.com/comments/2pfyg8.json?sort=top as an example) I'll get an json array with two objects. I want to loop over object number 2 because this is the object that has all the actual comments and the first object is the thread itself.

This seems like a challange in C#, or is atleast a challange for me. I use JSON.NET or Newtonsoft.Json to accomplish this and this is what I have so far:

var commentPath = $"http://www.reddit.com/comments/{questionId}.json?sort=top";
HttpResponseMessage commentResponse = await client.GetAsync(commentPath);
var commentJson = await response.Content.ReadAsStringAsync();
var answers = JsonConvert.DeserializeObject<dynamic>(commentJson);

int commentCount = 0;
foreach (var answerContainer in answers[1].data.children) { }

I have also tried to use http://json2csharp.com/ to generate the correct type for me to use instead of dynamic but it seems to be incorrect as well.

This is the error I recieve:

 System.ArgumentException: Accessed JObject values with invalid key value: 1. Object property name expected. vid Newtonsoft.Json.Linq.JObject.get_Item(Object key) vid CallSite.Target(Closure , CallSite , Object , Int32 )

I would be very glad if someone were able to help me in my quest to get the comment I am looking for.

2
  • 2
    Have you tried using the Paste JSON as classes feature in Visual Studio? blogs.msdn.microsoft.com/webdev/2012/12/18/… Commented Jan 29, 2017 at 11:32
  • @BenCottrell No, but when I am trying that, it identifies my content as xml and gives an error. :/ Commented Jan 29, 2017 at 11:37

1 Answer 1

1

Based on JSON response from Reddit, I generated this classes (Paste JSON as Classes function in Visual Studio):

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

public class Data
{
    public string modhash { get; set; }
    public Child[] children { get; set; }
    public object after { get; set; }
    public object before { get; set; }
}

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

public class Data1
{
    public bool contest_mode { get; set; }
    public object banned_by { get; set; }
    public Media_Embed media_embed { get; set; }
    public string subreddit { get; set; }
    public string selftext_html { get; set; }
    public string selftext { get; set; }
    public object likes { get; set; }
    public object suggested_sort { get; set; }
    public object[] user_reports { get; set; }
    public object secure_media { get; set; }
    public bool saved { get; set; }
    public string id { get; set; }
    public int gilded { get; set; }
    public Secure_Media_Embed secure_media_embed { get; set; }
    public bool clicked { get; set; }
    public object report_reasons { 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 string domain { get; set; }
    public bool hidden { get; set; }
    public int num_comments { get; set; }
    public string thumbnail { get; set; }
    public string subreddit_id { get; set; }
    public bool 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 archived { get; set; }
    public object removal_reason { get; set; }
    public bool stickied { get; set; }
    public bool is_self { get; set; }
    public bool hide_score { get; set; }
    public bool spoiler { get; set; }
    public string permalink { get; set; }
    public bool locked { get; set; }
    public string name { get; set; }
    public float created { get; set; }
    public string url { get; set; }
    public object author_flair_text { get; set; }
    public bool quarantine { get; set; }
    public string title { get; set; }
    public float created_utc { get; set; }
    public object link_flair_text { get; set; }
    public int ups { get; set; }
    public float upvote_ratio { get; set; }
    public object[] mod_reports { get; set; }
    public bool visited { get; set; }
    public object num_reports { get; set; }
    public object distinguished { get; set; }
    public string link_id { get; set; }
    public object replies { get; set; }
    public string parent_id { get; set; }
    public int controversiality { get; set; }
    public string body { get; set; }
    public string body_html { get; set; }
    public bool score_hidden { get; set; }
}

public class Media_Embed
{
}

public class Secure_Media_Embed
{
}

And then, working code looks like that:

using (var client = new HttpClient())
        {
            var commentPath = $"http://www.reddit.com/comments/{questionId}.json?sort=top";
            HttpResponseMessage commentResponse = client.GetAsync(commentPath).Result;
            var commentJson = commentResponse.Content.ReadAsStringAsync().Result;
            var answers = JsonConvert.DeserializeObject<reddit[]>(commentJson);

            int commentCount = 0;
            foreach (var answerContainer in answers[1].data.children)
            {
            }
        }
Sign up to request clarification or add additional context in comments.

4 Comments

This is exactly what I did before but then I get this error: Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {“name”:”value”}) into type ‘Sofie.Models.Reddit[]’ because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. But the json is an array!
I checked my solution with this url: reddit.com/comments/2pfyg8.json?sort=top and everything is working fine without any errors
If I use just the type and not an array it works but the children seems to be the thread and not the actual comments.
Just realized a huge mistake, var commentJson = await response.Content.ReadAsStringAsync(); should be var commentJson = await commentResponse.Content.ReadAsStringAsync(); since I am doing another request before this one in order to find the thread. With that change, it of course works just fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.