1

I am using the sample code provided by Brian Rogers on How do I use JSON.NET to deserialize into nested/recursive Dictionary and List? to convert a downloaded JSON file into a list of dictionaries (because I know that's what format it is in) and then return the value of the dictionary inside the list as text:

public static class JsonHelper
{
    public static object Deserialize(string json)
    {
        return ToObject(JToken.Parse(json));
    }

    private static object ToObject(JToken token)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                return token.Children<JProperty>()
                            .ToDictionary(prop => prop.Name,
                                          prop => ToObject(prop.Value));

            case JTokenType.Array:
                return token.Select(ToObject).ToList();

            default:
                return ((JValue)token).Value;
        }
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void btn1_Click(object sender, RoutedEventArgs e)
    {
        string wordType = "verb";
        var url = "http://api.wordnik.com:80/v4/word.json/" + txtBox.Text + "/definitions?limit=5&partOfSpeech=" + wordType + "&api_key=aaaa946871985c2eb2004061aba0695e00190753d6560ebea";
        var jsontext = new WebClient().DownloadString(url);
        object worddata = JsonHelper.Deserialize(jsontext);

        txtBlock.Text = worddata[0];
    }
}

The main focus is on a worddata variable. It is some sort of object but not a list of dictionaries. If it is any help I tried printing worddata to the console and it says System.Collections.Generic.List'1[System.Object].

Essentially I am trying to do what the json.load function does in python.

Example unparsed JSON:

[
  {
    "textProns": [],
    "sourceDictionary": "wiktionary",
    "exampleUses": [],
    "relatedWords": [],
    "labels": [
      {
        "type": "usage",
        "text": "nautical"
      }
    ],
    "citations": [],
    "word": "cat",
    "attributionUrl": "http://creativecommons.org/licenses/by-sa/3.0/",
    "attributionText": "from Wiktionary, Creative Commons Attribution/Share-Alike License",
    "partOfSpeech": "verb",
    "text": "To hoist (the anchor) by its ring so that it hangs at the cathead.",
    "score": 0.0
  },
  {
    "textProns": [],
    "sourceDictionary": "wiktionary",
    "exampleUses": [],
    "relatedWords": [],
    "labels": [
      {
        "type": "usage",
        "text": "nautical"
      }
    ],
    "citations": [],
    "word": "cat",
    "attributionUrl": "http://creativecommons.org/licenses/by-sa/3.0/",
    "attributionText": "from Wiktionary, Creative Commons Attribution/Share-Alike License",
    "partOfSpeech": "verb",
    "text": "To flog with a cat-o'-nine-tails.",
    "score": 0.0
  },
  {
    "textProns": [],
    "sourceDictionary": "wiktionary",
    "exampleUses": [],
    "relatedWords": [],
    "labels": [
      {
        "type": "register",
        "text": "slang"
      }
    ],
    "citations": [],
    "word": "cat",
    "attributionUrl": "http://creativecommons.org/licenses/by-sa/3.0/",
    "attributionText": "from Wiktionary, Creative Commons Attribution/Share-Alike License",
    "partOfSpeech": "verb",
    "text": "To vomit something.",
    "score": 0.0
  },
  {
    "textProns": [],
    "sourceDictionary": "wiktionary",
    "exampleUses": [],
    "relatedWords": [],
    "labels": [
      {
        "type": "grammar",
        "text": "transitive"
      },
      {
        "type": "field",
        "text": "computing"
      }
    ],
    "citations": [],
    "word": "cat",
    "attributionUrl": "http://creativecommons.org/licenses/by-sa/3.0/",
    "attributionText": "from Wiktionary, Creative Commons Attribution/Share-Alike License",
    "partOfSpeech": "verb",
    "text": "To apply the cat command to (one or more files).",
    "score": 0.0
  },
  {
    "textProns": [],
    "sourceDictionary": "wiktionary",
    "exampleUses": [],
    "relatedWords": [],
    "labels": [],
    "citations": [],
    "word": "cat",
    "attributionUrl": "http://creativecommons.org/licenses/by-sa/3.0/",
    "attributionText": "from Wiktionary, Creative Commons Attribution/Share-Alike License",
    "partOfSpeech": "verb",
    "text": "To dump large amounts of data on (an unprepared target) usually with no intention of browsing it carefully.",
    "score": 0.0
  }
]

Desired result:

"To hoist (the anchor) by its ring so that it hangs at the cathead."
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Eztain
  • 35
  • 1
  • 9

2 Answers2

1

This helper method returns a nested structure of List<object> and/or Dictionary<string, object>, in any combination, depending on what JSON you started with. It's intended to be used when you don't really know the structure of the JSON in advance (or you don't want to create classes for it) and you want to use the result with code that does not have awareness of Json.Net (i.e. you can't use JObject/JArray). If you do use this helper, you need to cast the result object appropriately at each level. So you'd need to do the following to get the text in your case:

var worddata = (List<object>)JsonHelper.Deserialize(jsontext);
var dict = (Dictionary<string, object>)worddata[0];
txtBlock.Text = (string)dict["text"];

Fiddle: https://dotnetfiddle.net/fhJQAS

This can get a little cumbersome if the hierarchy is deeply nested. In your case, I don't really see a need for the helper; you could just use JArray/JObject directly. This would allow you to simplify the code down to the following, although you still need a cast for the string:

var worddata = JArray.Parse(jsontext);
txtBlock.Text = (string)worddata[0]["text"];

Fiddle: https://dotnetfiddle.net/mmL6O8

Of course, that assumes you are familiar with JArray and JObject (also known as the LINQ-to-JSON API) and are comfortable with using it. It looks to me like your JSON is actually pretty well structured, so another alternative is just to make a couple of classes to hold the word items and deserialize directly into a list of those. For example:

public class WordDefinition
{
    public List<object> textProns { get; set; }
    public string sourceDictionary { get; set; }
    public List<object> exampleUses { get; set; }
    public List<object> relatedWords { get; set; }
    public List<Label> labels { get; set; }
    public List<object> citations { get; set; }
    public string word { get; set; }
    public string attributionUrl { get; set; }
    public string attributionText { get; set; }
    public string partOfSpeech { get; set; }
    public string text { get; set; }
    public double score { get; set; }
}

public class Label
{
    public string type { get; set; }
    public string text { get; set; }
}

Then everything is strongly typed so no casting is needed:

var worddata = JsonConvert.DeserializeObject<List<WordDefinition>>(jsontext);
txtBlock.Text = worddata[0].text;

Fiddle: https://dotnetfiddle.net/YOOC7B

Note, when creating the classes for the data, you can omit any members you don't care about, so if all you need is the text, it could be as simple as the following and it would still work:

public class WordDefinition
{
    public string text { get; set; }
}

Fiddle: https://dotnetfiddle.net/UktPo5

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
-1

You are print a List of object, so the output is normal. If you want the Json representation, convert it Json again

txtBloct.Text = JsonConvert.SerializeObject(worddata[0])

Or if you want to print the list as string, iterate through it and print the objects

Yves Israel
  • 408
  • 3
  • 5