Deserializing JSON to .NET object using Newtonsoft (or LINQ to JSON maybe?)

708,835

Solution 1

If you just need to get a few items from the JSON object, I would use Json.NET's LINQ to JSON JObject class. For example:

JToken token = JObject.Parse(stringFullOfJson);

int page = (int)token.SelectToken("page");
int totalPages = (int)token.SelectToken("total_pages");

I like this approach because you don't need to fully deserialize the JSON object. This comes in handy with APIs that can sometimes surprise you with missing object properties, like Twitter.

Documentation: Serializing and Deserializing JSON with Json.NET and LINQ to JSON with Json.NET

Solution 2

You can use the C# dynamic type to make things easier. This technique also makes re-factoring simpler as it does not rely on magic-strings.

JSON

The JSON string below is a simple response from an HTTP API call, and it defines two properties: Id and Name.

{"Id": 1, "Name": "biofractal"}

C#

Use JsonConvert.DeserializeObject<dynamic>() to deserialize this string into a dynamic type then simply access its properties in the usual way.

dynamic results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;

If you specify the type of the results variable as dynamic, instead of using the var keyword, then the property values will correctly deserialize, e.g. Id to an int and not a JValue (thanks to GFoley83 for the comment below).

Note: The NuGet link for the Newtonsoft assembly is http://nuget.org/packages/newtonsoft.json.

Package: You can also add the package with nuget live installer, with your project opened just do browse package and then just install it install, unistall, update, it will just be added to your project under Dependencies/NuGet

Solution 3

With the dynamic keyword, it becomes really easy to parse any object of this kind:

dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
var page = x.page;
var total_pages = x.total_pages
var albums = x.albums;
foreach(var album in albums)
{
    var albumName = album.name;

    // Access album data;
}

Solution 4

If, like me, you prefer to deal with strongly typed objects** go with:

MyObj obj =  JsonConvert.DeserializeObject<MyObj>(jsonString);

This way you get to use intellisense and compile time type error checking.

You can easily create the required objects by copying your JSON into memory and pasting it as JSON objects (Visual Studio -> Edit -> Paste Special -> Paste JSON as Classes).

See here if you don't have that option in Visual Studio.

You will also need to make sure your JSON is valid. Add your own object at the start if it is just an array of objects. i.e. {"obj":[{},{},{}]}

** I know that dynamic makes things easier sometimes but I'm a bit ol'skool with this.

Solution 5

Correct me if I'm mistaken, but the previous example, I believe, is just slightly out of sync with the latest version of James Newton's Json.NET library.

var o = JObject.Parse(stringFullOfJson);
var page = (int)o["page"];
var totalPages = (int)o["total_pages"];
Share:
708,835
J Benjamin
Author by

J Benjamin

Updated on July 08, 2022

Comments

  • J Benjamin
    J Benjamin almost 2 years

    I know there are a few posts about Newtonsoft so hopefully this isn't exactly a repeat...I'm trying to convert JSON data returned by Kazaa's API into a nice object of some kind

    WebClient client = new WebClient();
    Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
    StreamReader reader = new StreamReader(stream);
    
    List<string> list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(reader.Read().ToString());
    
    foreach (string item in list)
    {
        Console.WriteLine(item);
    }
    
    //Console.WriteLine(reader.ReadLine());
    stream.Close();
    

    That JsonConvert line is just the most recent one I was trying...I'm not quite getting it and was hoping to eliminate some footwork by asking you guys. I was originally trying to convert it into a Dictionary or something...and actually, I just need to snag a couple of values in there so judging by the documentation, maybe Newtonsoft's LINQ to JSON might be a better choice? Thoughts/Links?

    Here is an example of the JSON return data:

    {
      "page": 1,
      "total_pages": 8,
      "total_entries": 74,
      "q": "muse",
      "albums": [
        {
          "name": "Muse",
          "permalink": "Muse",
          "cover_image_url": "http://image.kazaa.com/images/69/01672812 1569/Yaron_Herman_Trio/Muse/Yaron_Herman_Trio-Muse_1.jpg",
          "id": 93098,
          "artist_name": "Yaron Herman Trio"
        },
        {
          "name": "Muse",
          "permalink": "Muse",
          "cover_image_url": "htt p://image.kazaa.com/images/54/888880301154/Candy_Lo/Muse/Candy_Lo-Muse_1.jpg",
          "i d": 102702,
          "artist_name": "\u76e7\u5de7\u97f3"
        },
        {
          "name": "Absolution",
          "permalink": " Absolution",
          "cover_image_url": "http://image.kazaa.com/images/65/093624873365/Mus e/Absolution/Muse-Absolution_1.jpg",
          "id": 48896,
          "artist_name": "Muse"
        },
        {
          "name": "Ab solution",
          "permalink": "Absolution-2",
          "cover_image_url": "http://image.kazaa.com/i mages/20/825646911820/Muse/Absolution/Muse-Absolution_1.jpg",
          "id": 118573,
          "artist _name": "Muse"
        },
        {
          "name": "Black Holes And Revelations",
          "permalink": "Black-Holes-An d-Revelations",
          "cover_image_url": "http://image.kazaa.com/images/66/093624428466/ Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1.jpg",
          "id": 48813,
          "artist_name": "Muse"
        },
        {
          "name": "Black Holes And Revelations",
          "permalink": "Bla ck-Holes-And-Revelations-2",
          "cover_image_url": "http://image.kazaa.com/images/86/ 825646911486/Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1 .jpg",
          "id": 118543,
          "artist_name": "Muse"
        },
        {
          "name": "Origin Of Symmetry",
          "permalink": "Origin-Of-Symmetry",
          "cover_image_url": "http://image.kazaa.com/images/29/825646 912629/Muse/Origin_Of_Symmetry/Muse-Origin_Of_Symmetry_1.jpg",
          "id": 120491,
          "artis t_name": "Muse"
        },
        {
          "name": "Showbiz",
          "permalink": "Showbiz",
          "cover_image_url": "http: //image.kazaa.com/images/68/825646182268/Muse/Showbiz/Muse-Showbiz_1.jpg",
          "id": 60444,
          "artist_name": "Muse"
        },
        {
          "name": "Showbiz",
          "permalink": "Showbiz-2",
          "cover_imag e_url": "http://image.kazaa.com/images/50/825646912650/Muse/Showbiz/Muse-Showbiz_ 1.jpg",
          "id": 118545,
          "artist_name": "Muse"
        },
        {
          "name": "The Resistance",
          "permalink": "T he-Resistance",
          "cover_image_url": "http://image.kazaa.com/images/36/825646864836/ Muse/The_Resistance/Muse-The_Resistance_1.jpg",
          "id": 121171,
          "artist_name": "Muse"
        }
      ],
      "per_page": 10
    }
    

    I did some more reading and found Newtonsoft's LINQ to JSON is exactly what I wanted...using WebClient, Stream, StreamReader, and Newtonsoft...I can hit Kazaa for JSON data, extract a URL, download the file, and do it all in like seven lines of code! I love it.

    WebClient client = new WebClient();
    Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
    StreamReader reader = new StreamReader(stream);
    
    Newtonsoft.Json.Linq.JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
    
    // Instead of WriteLine, 2 or 3 lines of code here using WebClient to download the file
    Console.WriteLine((string)jObject["albums"][0]["cover_image_url"]);
    stream.Close();
    

    This post gets so many hits I thought it might be helpful to include the "using" bits that are discussed in the comments.

    using(var client = new WebClient())
    using(var stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album"))
    using (var reader = new StreamReader(stream))
    {
        var jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
        Console.WriteLine((string) jObject["albums"][0]["cover_image_url"]);
    }
    
  • J Benjamin
    J Benjamin over 13 years
    ya I've actually done a bit more reading and testing...found this to be a nice way of doing it as well...Newtonsoft, pretty nice library, I'll post my example for others
  • J Benjamin
    J Benjamin over 13 years
    posted a rough example of how I was doing it...not quite the same, I see you suggested JToken.Parse...not sure of the differences between the two yet but ya, good stuff!
  • J Benjamin
    J Benjamin over 13 years
    thanks for your response Rick, ya that looks similar to the examples I found in the most recent documentation as well.
  • arcain
    arcain over 13 years
    @Jbenjamin Thanks! That was a typo. JToken is the base class for JObject, and it's just my personal preference to work with the more abstract type. Thanks for calling that to my attention.
  • Admin
    Admin over 13 years
    Yeah, since arcain fixed the typo, my comment now just looks nitpicky :'(. I originally posted because I didn't recognize JToken.Parse.
  • arcain
    arcain over 13 years
    Not nitpicky at all - there definitely was a mistake, and there's always more than one way to do it. By the way, my version of Json.NET does support the syntax using the indexer on JObject, but the code I modified for my answer was pulled from code making use of an overload of the SelectToken method so I could suppress exceptions if the token wasn't found: JToken JToken.SelectToken(string tokenName, bool errorWhenNoMatch), so that's where the verbosity came from.
  • TYRONEMICHAEL
    TYRONEMICHAEL over 12 years
    Sorry, but should it be JToken, or JObject? The above code is still throwing the error "Error reading JObject from JsonReader" every now and then.
  • arcain
    arcain over 12 years
    @Tyrone I haven't experienced the problem you encountered. From what you list as the exception, and browsing through the Json.NET source, it seems related to reading from the JsonReader. If you change the first line to JObject token = JObject.Parse(stringFullOfJson); does that seem to help?
  • TYRONEMICHAEL
    TYRONEMICHAEL over 12 years
    @Arcain, thats what I originally had. I came to this post and tried the JObject and JToken. I ran two instances, one locally, and one on the server, and both failed on the same tweet at JToken json = JObject.Parse(ResponseStream.ReadLine());. This only seems to happen on the +- 20th tweet. Thanks so much for your help.
  • arcain
    arcain over 12 years
    @Tyrone Sure, no problem. I actually use this code for Twitter status parsing as well, and I've had to write quite a bit of error handling around the calls to Twitter since they can be spotty at times. If you're not already doing so, I'd recommend dumping the raw JSON response from Twitter to a log before attempting to parse it. Then if it fails, you can at least see if you received something funky over the wire.
  • arcain
    arcain almost 12 years
    @james Thanks for adding the documentation links. I didn't think to include those.
  • Pranav
    Pranav over 9 years
    I was using the same piece of code as above to deserialize the twitter response with newtonsoft.dll version 4.5.6 and it was working fine ..but after update it to version 5.0.6 .. it started throwing error... any idea why ??
  • MSTdev
    MSTdev over 9 years
    Good for dynamic object ,when we know or we have c# class so we can consume as a C# class on replace of dynamic e.g. <Myclass>.
  • batoutofhell
    batoutofhell about 8 years
    I wanted to know how to loop through the results and this took way too long to find... thanks!!
  • GFoley83
    GFoley83 almost 8 years
    Use dynamic results = JsonConvert.DeserializeObject<ExpandoObject>(json); here FTW. It will correctly deserialize Id to an int and not a JValue. See here:dotnetfiddle.net/b0WxGJ
  • Adam
    Adam about 7 years
    @biofractal How would I do this dynamic results = JsonConvert.DeserializeObject<dynamic>(json); in VB.NET? Dim results As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Object)(json) does not work.
  • netfed
    netfed over 6 years
    I find this method very nice for two reasons: 1) when you do not care about data type (everything is string), and 2) it is convenient to work with a dictionary of the values
  • Sloomy
    Sloomy almost 6 years
  • j.hull
    j.hull almost 5 years
    Very much my preferred approached to programming. I like strong typed objects. Thanks, for I used and modified this code.
  • ToolmakerSteve
    ToolmakerSteve over 4 years
  • ToolmakerSteve
    ToolmakerSteve about 3 years
    codes.Add(code?.ToString()) will add a null for any missing code. The ? is not in a position that can stop codes.Add from executing. You probably want if (code != null) ...
  • ToolmakerSteve
    ToolmakerSteve about 3 years
    FWIW, I finally tested ExpandoObject in VB. I found it convenient to cast to IDictionary: Dim dict As IDictionary(Of String, Object) = JsonConvert.DeserializeObject(Of ExpandoObject)(json) Dim name = dict("Name")
  • public wireless
    public wireless over 2 years
    That paste to JSON feature rocks! Saved me a boatload of time