340

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"]);
}
Tim Sylvester
  • 22,897
  • 2
  • 80
  • 94
J Benjamin
  • 4,722
  • 6
  • 29
  • 39
  • 9
    Slick example, thanks. Just a suggestion: you may have left this off for brevity, but since `WebClient`, `Stream` and `StreamReader` all implement `IDisposable`, you might want to add some `using` blocks to your code. – arcain Jan 20 '11 at 17:35
  • ah yes, good call...(ya this was actually just a console app I was running real quick to research for the tasks I have coming up) Now off to research the last piece of the puzzle, HLS+AES encryption :) ugh...lol – J Benjamin Jan 20 '11 at 17:58
  • Does the newtonsoft solution doesn't fully deserialize the JSON as well? Just like @arcain's solution do. – AXMIM Jun 28 '16 at 14:41
  • Note the link here: [LINQ to JSON](https://www.newtonsoft.com/json/help/html/LINQtoJSON.htm) – yu yang Jian Jun 19 '18 at 04:21

12 Answers12

288

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

anastaciu
  • 23,467
  • 7
  • 28
  • 53
biofractal
  • 18,963
  • 12
  • 70
  • 116
  • 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 ?? – Pranav Nov 11 '14 at 11:19
  • 1
    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. . – MSTdev Jan 21 '15 at 07:17
  • 2
    Use `dynamic results = JsonConvert.DeserializeObject(json);` here FTW. It will correctly deserialize `Id` to an int and not a `JValue`. See here:https://dotnetfiddle.net/b0WxGJ – GFoley83 May 31 '16 at 22:53
  • @biofractal How would I do this `dynamic results = JsonConvert.DeserializeObject(json); ` in VB.NET? `Dim results As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Object)(json)` does not work. – Adam May 02 '17 at 13:38
  • @Flo try [...DeserializeObject(Of System.Dynamic.ExpandoObject)](https://stackoverflow.com/a/49952995/199364). – ToolmakerSteve Oct 01 '19 at 09:20
  • 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")` – ToolmakerSteve Mar 10 '21 at 01:28
275

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
arcain
  • 14,920
  • 6
  • 55
  • 75
  • 1
    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 Jan 20 '11 at 16:56
  • 1
    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 Jan 20 '11 at 17:07
  • 1
    @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. – arcain Jan 20 '11 at 18:05
  • 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. – TYRONEMICHAEL Feb 03 '12 at 08:15
  • @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? – arcain Feb 03 '12 at 08:46
  • @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. – TYRONEMICHAEL Feb 03 '12 at 09:36
  • 2
    @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 Feb 03 '12 at 16:32
  • @james Thanks for adding the documentation links. I didn't think to include those. – arcain Aug 02 '12 at 18:55
45

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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
26

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.

Guy Lowe
  • 2,115
  • 1
  • 27
  • 37
23

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"];
Rick Leitch
  • 231
  • 1
  • 2
  • 1
    thanks for your response Rick, ya that looks similar to the examples I found in the most recent documentation as well. – J Benjamin Jan 20 '11 at 18:01
  • 1
    Yeah, since arcain fixed the typo, my comment now just looks nitpicky :'(. I originally posted because I didn't recognize JToken.Parse. – Rick Leitch Jan 20 '11 at 19:16
  • 1
    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. – arcain Jan 20 '11 at 19:42
13

Dynamic List Loosely Typed - Deserialize and read the values

// First serializing
dynamic collection = new { stud = stud_datatable }; // The stud_datable is the list or data table
string jsonString = JsonConvert.SerializeObject(collection);


// Second Deserializing
dynamic StudList = JsonConvert.DeserializeObject(jsonString);

var stud = StudList.stud;
foreach (var detail in stud)
{
    var Address = detail["stud_address"]; // Access Address data;
}
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
9

I like this method:

using Newtonsoft.Json.Linq;
// jsonString is your JSON-formatted string
JObject jsonObj = JObject.Parse(jsonString);
Dictionary<string, object> dictObj = jsonObj.ToObject<Dictionary<string, object>>();

You can now access anything you want using the dictObj as a dictionary. You can also use Dictionary<string, string> if you prefer to get the values as strings.

You can use this same method to cast as any kind of .NET object.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Blairg23
  • 11,334
  • 6
  • 72
  • 72
  • 2
    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 – netfed Oct 15 '17 at 18:01
7

Also, if you're just looking for a specific value nested within the JSON content you can do something like so:

yourJObject.GetValue("jsonObjectName").Value<string>("jsonPropertyName");

And so on from there.

This could help if you don't want to bear the cost of converting the entire JSON into a C# object.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tony
  • 200
  • 2
  • 5
2

i craeted an Extionclass for json :

 public static class JsonExtentions
    {
        public static string SerializeToJson(this object SourceObject) { return Newtonsoft.Json.JsonConvert.SerializeObject(SourceObject); }


        public static T JsonToObject<T>(this string JsonString) { return (T)Newtonsoft.Json.JsonConvert.DeserializeObject<T>(JsonString); }
}

Design-Pattern:

 public class Myobject
    {
        public Myobject(){}
        public string prop1 { get; set; }

        public static Myobject  GetObject(string JsonString){return  JsonExtentions.JsonToObject<Myobject>(JsonString);}
        public  string ToJson(string JsonString){return JsonExtentions.SerializeToJson(this);}
    }

Usage:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);
Sloomy
  • 151
  • 1
  • 6
  • https://stackoverflow.com/questions/2246694/how-to-convert-json-object-to-custom-c-sharp-object – Sloomy Jun 08 '18 at 18:53
1

Fairly late to this party, but I came across this issue myself today at work. Here is how I solved the issue.

I was accessing a 3rd party API to retrieve a list of books. The object returned a massive JSON object containing roughly 20+ fields, of which I only needed the ID as a List string object. I used linq on the dynamic object to retrieve the specific field I needed and then inserted it into my List string object.

dynamic content = JsonConvert.DeserializeObject(requestContent);
var contentCodes = ((IEnumerable<dynamic>)content).Where(p => p._id != null).Select(p=>p._id).ToList();

List<string> codes = new List<string>();

foreach (var code in contentCodes)
{
    codes.Add(code?.ToString());
}
todd.pund
  • 689
  • 2
  • 11
  • 36
  • 1
    `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 Mar 09 '21 at 23:53
0

Finally Get State Name From JSON

Thankyou!

Imports System
Imports System.Text
Imports System.IO
Imports System.Net
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.collections.generic

Public Module Module1
    Public Sub Main()

         Dim url As String = "http://maps.google.com/maps/api/geocode/json&address=attur+salem&sensor=false"
            Dim request As WebRequest = WebRequest.Create(url)
        dim response As WebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        dim reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
          Dim dataString As String = reader.ReadToEnd()

        Dim getResponse As JObject = JObject.Parse(dataString)

        Dim dictObj As Dictionary(Of String, Object) = getResponse.ToObject(Of Dictionary(Of String, Object))()
        'Get State Name
        Console.WriteLine(CStr(dictObj("results")(0)("address_components")(2)("long_name")))
    End Sub
End Module
0

Deserializing using JsonConvert.DeserializeObject() function

public class ApiValues
    {
        [JsonProperty("Address")]
        public string Address { get; set; }

        [JsonProperty("BaseUrl")]
        public string BaseUrl{ get; set; }
    }

var json = 
{ 
    "Address":"some-address",
    "BaseUrl":"some-url-value"
}


var values = JsonConvert.DeserializeObject<ApiValues>(json);

Dev-lop-er
  • 578
  • 1
  • 7
  • 16