Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Using JSON.NET for dynamic JSON parsing


:P
On this page:

With the release of ASP.NET Web API as part of .NET 4.5 and MVC 4.0, JSON.NET has effectively pushed out the .NET native serializers to become the default serializer for Web API. JSON.NET is vastly more flexible than the built in DataContractJsonSerializer or the older JavaScript serializer. The DataContractSerializer in particular has been very problematic in the past because it can't deal with untyped objects for serialization - like values of type object, or anonymous types which are quite common these days. The JavaScript Serializer that came before it actually does support non-typed objects for serialization but it can't do anything with untyped data coming in from JavaScript and it's overall model of extensibility was pretty limited (JavaScript Serializer is what MVC uses for JSON responses).

JSON.NET provides a robust JSON serializer that has both high level and low level components, supports binary JSON, JSON contracts, Xml to JSON conversion, LINQ to JSON and many, many more features than either of the built in serializers. ASP.NET Web API now uses JSON.NET as its default serializer and is now pulled in as a NuGet dependency into Web API projects, which is great.

Dynamic JSON Parsing

One of the features that I think is getting ever more important is the ability to serialize and deserialize arbitrary JSON content dynamically - that is without mapping the JSON captured directly into a .NET type as DataContractSerializer or the JavaScript Serializers do. Sometimes it isn't possible to map types due to the differences in languages (think collections, dictionaries etc), and other times you simply don't have the structures in place or don't want to create them to actually import the data.

If this topic sounds familiar - you're right! I wrote about dynamic JSON parsing a few months back before JSON.NET was added to Web API and when Web API and the System.Net HttpClient libraries included the System.Json classes like JsonObject and JsonArray. With the inclusion of JSON.NET in Web API these classes are now obsolete and didn't ship with Web API or the client libraries. I re-linked my original post to this one. In this post I'll discus JToken, JObject and JArray which are the dynamic JSON objects that make it very easy to create and retrieve JSON content on the fly without underlying types.

Why Dynamic JSON?

So, why Dynamic JSON parsing rather than strongly typed parsing? Since applications are interacting more and more with third party services it becomes ever more important to have easy access to those services with easy JSON parsing. Sometimes it just makes lot of sense to pull just a small amount of data out of large JSON document received from a service, because the third party service isn't directly related to your application's logic most of the time - and it makes little sense to map the entire service structure in your application.

For example, recently I worked with the Google Maps Places API to return information about businesses close to me (or rather the app's) location. The Google API returns a ton of information that my application had no interest in - all I needed was few values out of the data. Dynamic JSON parsing makes it possible to map this data, without having to map the entire API to a C# data structure. Instead I could pull out the three or four values I needed from the API and directly store it on my business entities that needed to receive the data - no need to map the entire Maps API structure.

Getting JSON.NET

The easiest way to use JSON.NET is to grab it via NuGet and add it as a reference to your project. You can add it to your project with:

PM> Install-Package Newtonsoft.Json

From the Package Manager Console or by using Manage NuGet Packages in your project References. As mentioned if you're using ASP.NET Web API or MVC 4 JSON.NET will be automatically added to your project.

Alternately you can also go to the CodePlex site and download the latest version including source code:

http://json.codeplex.com/

Creating JSON on the fly with JObject and JArray

Let's start with creating some JSON on the fly. It's super easy to create a dynamic object structure with any of the JToken derived JSON.NET objects. The most common JToken derived classes you are likely to use are JObject and JArray.

JToken implements IDynamicMetaProvider and so uses the dynamic  keyword extensively to make it intuitive to create object structures and turn them into JSON via dynamic object syntax. Here's an example of creating a music album structure with child songs using JObject for the base object and songs and JArray for the actual collection of songs:

[TestMethod]
public void JObjectOutputTest()
{
    // strong typed instance 
    var jsonObject = new JObject();
                        
    // you can explicitly add values here using class interface
    jsonObject.Add("Entered", DateTime.Now);

    // or cast to dynamic to dynamically add/read properties    dynamic album = jsonObject;

    album.AlbumName = "Dirty Deeds Done Dirt Cheap";
    album.Artist = "AC/DC";
    album.YearReleased = 1976;

    album.Songs = new JArray() as dynamic;
            
    dynamic song = new JObject();
    song.SongName = "Dirty Deeds Done Dirt Cheap";
    song.SongLength = "4:11";
    album.Songs.Add(song);

    song = new JObject();
    song.SongName = "Love at First Feel";
    song.SongLength = "3:10";
    album.Songs.Add(song);

    Console.WriteLine(album.ToString());
}

This produces a complete JSON structure:

{
  "Entered": "2012-08-18T13:26:37.7137482-10:00",
  "AlbumName": "Dirty Deeds Done Dirt Cheap",
  "Artist": "AC/DC",
  "YearReleased": 1976,
  "Songs": [
    {
      "SongName": "Dirty Deeds Done Dirt Cheap",
      "SongLength": "4:11"
    },
    {
      "SongName": "Love at First Feel",
      "SongLength": "3:10"
    }
  ]
}

Notice that JSON.NET does a nice job formatting the JSON, so it's easy to read and paste into blog posts 😃. JSON.NET includes a bunch of configuration options that control how JSON is generated. Typically the defaults are just fine, but you can override with the JsonSettings object for most operations.

The important thing about this code is that there's no explicit type used for holding the values to serialize to JSON. Rather the JSON.NET objects are the containers that receive the data as I build up my JSON structure dynamically, simply by adding properties. This means this code can be entirely driven at runtime without compile time restraints of structure for the JSON output.

Here I use JObject to create a album 'object' and immediately cast it to dynamic. JObject() is kind of similar in behavior to ExpandoObject in that it allows you to add properties by simply assigning to them. Internally, JObject values are stored in pseudo collections of key value pairs that are exposed as properties through the IDynamicMetaObject interface exposed in JSON.NET's JToken base class.

For objects the syntax is very clean - you add simple typed values as properties. For objects and arrays you have to explicitly create new JObject or JArray, cast them to dynamic and then add properties and items to them. Always remember though these values are dynamic - which means no Intellisense and no compiler type checking. It's up to you to ensure that the names and values you create are accessed consistently and without typos in your code.

Note that you can also access the JObject instance directly (not as dynamic) and get access to the underlying JObject type. This means you can assign properties by string, which can be useful for fully data driven JSON generation from other structures.

Below you can see both styles of access next to each other:

// strong type instance 
var jsonObject = new JObject();

// you can explicitly add values here
jsonObject.Add("Entered", DateTime.Now);

// expando style instance you can just 'use' properties
dynamic album = jsonObject;

album.AlbumName = "Dirty Deeds Done Dirt Cheap";

JContainer (the base class for JObject and JArray) is a collection so you can also iterate over the properties at runtime easily:

foreach (var item in jsonObject)
{
    Console.WriteLine(item.Key + " " + item.Value.ToString());
}

The functionality of the JSON objects are very similar to .NET's ExpandObject and if you used it before, you're already familiar with how the dynamic interfaces to the JSON objects works.

Importing JSON with JObject.Parse() and JArray.Parse()

The JValue structure supports importing JSON via the Parse() and Load() methods which can read JSON data from a string or various streams respectively. Essentially JValue includes the core JSON parsing to turn a JSON string into a collection of JsonValue objects that can be then referenced using familiar dynamic object syntax.

Here's a simple example:

public void JValueParsingTest()
{
    var jsonString = @"{""Name"":""Rick"",""Company"":""West Wind"",
                        ""Entered"":""2012-03-16T00:03:33.245-10:00""}";

    dynamic json = JValue.Parse(jsonString);

    // values require casting
    string name = json.Name;
    string company = json.Company;
    DateTime entered = json.Entered;

    Assert.AreEqual(name, "Rick");
    Assert.AreEqual(company, "West Wind");            
}

The JSON string represents an object with three properties which is parsed into a JObject class and cast to dynamic. Once cast to dynamic I can then go ahead and access the object using familiar object syntax.

Note that the actual values - json.Name, json.Company, json.Entered - are actually of type JToken and I have to cast them to their appropriate types first before I can do type comparisons as in the Asserts at the end of the test method. This is required because of the way that dynamic types work which can't determine the type based on the method signature of the Assert.AreEqual(object,object) method. I have to either assign the dynamic value to a variable as I did above, or explicitly cast ( (string) json.Name) in the actual method call.

The JSON structure can be much more complex than this simple example. Here's another example of an array of albums serialized to JSON and then parsed through with JsonValue():

[TestMethod]
public void JsonArrayParsingTest()
{
    var jsonString = @"[
{
""Id"": ""b3ec4e5c"",
""AlbumName"": ""Dirty Deeds Done Dirt Cheap"",
""Artist"": ""AC/DC"",
""YearReleased"": 1976,
""Entered"": ""2012-03-16T00:13:12.2810521-10:00"",
""AlbumImageUrl"": ""http://ecx.images-amazon.com/images/I/61kTaH-uZBL._AA115_.jpg"",
""AmazonUrl"": ""http://www.amazon.com/gp/product/…ASIN=B00008BXJ4"",
""Songs"": [
    {
    ""AlbumId"": ""b3ec4e5c"",
    ""SongName"": ""Dirty Deeds Done Dirt Cheap"",
    ""SongLength"": ""4:11""
    },
    {
    ""AlbumId"": ""b3ec4e5c"",
    ""SongName"": ""Love at First Feel"",
    ""SongLength"": ""3:10""
    },
    {
    ""AlbumId"": ""b3ec4e5c"",
    ""SongName"": ""Big Balls"",
    ""SongLength"": ""2:38""
    }
]
},
{
""Id"": ""7b919432"",
""AlbumName"": ""End of the Silence"",
""Artist"": ""Henry Rollins Band"",
""YearReleased"": 1992,
""Entered"": ""2012-03-16T00:13:12.2800521-10:00"",
""AlbumImageUrl"": ""http://ecx.images-amazon.com/images/I/51FO3rb1tuL._SL160_AA160_.jpg"",
""AmazonUrl"": ""http://www.amazon.com/End-Silence-Rollins-Band/dp/B0000040OX/ref=sr_1_5?ie=UTF8&qid=1302232195&sr=8-5"",
""Songs"": [
    {
    ""AlbumId"": ""7b919432"",
    ""SongName"": ""Low Self Opinion"",
    ""SongLength"": ""5:24""
    },
    {
    ""AlbumId"": ""7b919432"",
    ""SongName"": ""Grip"",
    ""SongLength"": ""4:51""
    }
]
}
]";

    JArray jsonVal = JArray.Parse(jsonString) as JArray;
    dynamic albums = jsonVal;

    foreach (dynamic album in albums)
    {
        Console.WriteLine(album.AlbumName + " (" + album.YearReleased.ToString() + ")");
        foreach (dynamic song in album.Songs)
        {
            Console.WriteLine("\t" + song.SongName);
        }
    }

    Console.WriteLine(albums[0].AlbumName);
    Console.WriteLine(albums[0].Songs[1].SongName);
}

JObject and JArray in ASP.NET Web API

Of course these types also work in ASP.NET Web API controller methods. If you want you can accept parameters using these object or return them back to the server.

The following contrived example receives dynamic JSON input, and then creates a new dynamic JSON object and returns it based on data from the first:

[HttpPost]
public JObject PostAlbumJObject(JObject jAlbum)
{
    // dynamic input from inbound JSON
    dynamic album = jAlbum;

    // create a new JSON object to write out
    dynamic newAlbum = new JObject();

    // Create properties on the new instance
    // with values from the first
    newAlbum.AlbumName = album.AlbumName + " New";
    newAlbum.NewProperty = "something new";
    newAlbum.Songs = new JArray();
    
    foreach (dynamic song in album.Songs)
    {
        song.SongName = song.SongName + " New"; 
        newAlbum.Songs.Add(song);                
    }
            
    return newAlbum;
}

The raw POST request to the server looks something like this:

POST http://localhost/aspnetwebapi/samples/PostAlbumJObject HTTP/1.1
User-Agent: Fiddler
Content-type: application/json
Host: localhost
Content-Length: 88

{AlbumName: "Dirty Deeds",Songs:[ { SongName: "Problem Child"},{ SongName: "Squealer"}]}

and the output that comes back looks like this:

{
  "AlbumName": "Dirty Deeds New",
  "NewProperty": "something new",
  "Songs": [
    {
      "SongName": "Problem Child New"
    },
    {
      "SongName": "Squealer New"
    }
  ]
}

The original values are echoed back with something extra appended to demonstrate that we're working with a new object.

When you receive or return a JObject, JValue, JToken or JArray instance in a Web API method, Web API ignores normal content negotiation and assumes your content is going to be received and returned as JSON, so effectively the parameter and result type explicitly determines the input and output format which is nice.

Dynamic to Strong Type Mapping

You can also map JObject and JArray instances to a strongly typed object, so you can mix dynamic and static typing in the same piece of code. Using the 2 Album jsonString shown earlier, the code below takes an array of albums and picks out only a single album and casts that album to a static Album instance.

[TestMethod]
public void JsonParseToStrongTypeTest()
{
    JArray albums = JArray.Parse(jsonString) as JArray;

    // pick out one album
    JObject jalbum = albums[0] as JObject;

    // Copy to a static Album instance
    Album album = jalbum.ToObject<Album>();

    Assert.IsNotNull(album);
    Assert.AreEqual(album.AlbumName,jalbum.Value<string>("AlbumName"));
    Assert.IsTrue(album.Songs.Count > 0);
}

This is pretty damn useful for the scenario I mentioned earlier - you can read a large chunk of JSON and dynamically walk the property hierarchy down to the item you want to access, and then either access the specific item dynamically (as shown earlier) or map a part of the JSON to a strongly typed object. That's very powerful if you think about it - it leaves you in total control to decide what's dynamic and what's static.

Strongly typed JSON Parsing

With all this talk of dynamic let's not forget that JSON.NET of course also does strongly typed serialization which is drop dead easy. Here's a simple example on how to serialize and deserialize an object with JSON.NET:

[TestMethod]
public void StronglyTypedSerializationTest()
{

    // Demonstrate deserialization from a raw string
    var album = new Album()
    {
        AlbumName = "Dirty Deeds Done Dirt Cheap",
        Artist = "AC/DC",
        Entered = DateTime.Now,
        YearReleased = 1976,
        Songs =  new List<Song>() 
        {
            new Song()
            {
                SongName = "Dirty Deeds Done Dirt Cheap",
                SongLength = "4:11"
            },
            new Song()
            {
                SongName = "Love at First Feel",
                SongLength = "3:10"
            }
        }
    };
            
    // serialize to string            
    string json2 = JsonConvert.SerializeObject(album,Formatting.Indented);

    Console.WriteLine(json2);

    // make sure we can serialize back
    var album2 = JsonConvert.DeserializeObject<Album>(json2);

    Assert.IsNotNull(album2);
    Assert.IsTrue(album2.AlbumName == "Dirty Deeds Done Dirt Cheap");
    Assert.IsTrue(album2.Songs.Count == 2);
}

JsonConvert is a high level static class that wraps lower level functionality, but you can also use the JsonSerializer class, which allows you to serialize/parse to and from streams. It's a little more work, but gives you a bit more control. The functionality available is easy to discover with Intellisense, and that's good because there's not a lot in the way of documentation that's actually useful.

Summary

JSON.NET is a pretty complete JSON implementation with lots of different choices for JSON parsing from dynamic parsing to static serialization, to complex querying of JSON objects using LINQ. It's good to see this open source library getting integrated into .NET, and pushing out the old and tired stock .NET parsers so that we finally have a bit more flexibility - and extensibility - in our JSON parsing. Good to go!

Resources

this post created and published with Markdown Monster
Posted in .NET  Web Api  AJAX  

The Voices of Reason


 

James Newton-King
August 30, 2012

# re: Using JSON.NET for dynamic JSON parsing

If you need additional help the Json.NET documentation for working with dynamic JSON can be found here - http://james.newtonking.com/projects/json/help/?topic=html/LINQtoJSON.htm

Jim Jackson
August 30, 2012

# re: Using JSON.NET for dynamic JSON parsing

Thanks!

These parsing operations have been troubling me for a while and I never found that "just right" combination of dynamic and JObject/JValue/JArray. If you pass the JSON string back from the client, this could work just as easily in MVC3.

Tiendq
August 30, 2012

# re: Using JSON.NET for dynamic JSON parsing

What will happen if jalbum has a property that does not exist in album? and vice versa?

// Copy to a static Album instance
Album album = jalbum.ToObject<Album>();

I did not see any help here: http://james.newtonking.com/projects/json/help/html/M_Newtonsoft_Json_Linq_JToken_ToObject__1.htm

Thanks,

ügyviteli szoftverek
September 01, 2012

# re: Using JSON.NET for dynamic JSON parsing

+1 for the "Strongly typed JSON Parsing". I'm working in .NET-mixed-PHP so it's a treasue for me.

MB
September 06, 2012

# re: Using JSON.NET for dynamic JSON parsing

Rick, how about for WWWC? Will you be able to support it there as well? I posted some feedback in the forum a week or two ago that this is not working as expected. WWWC still having issues with JSON dates and complex strings.

Rick Strahl
September 06, 2012

# re: Using JSON.NET for dynamic JSON parsing

@MB - it might be possible to use JSON.NET's dynamic parsing with COM Interop from VFP, but I think it'd be fairly slow to read the data out as you would get back a COM object. Worth a try - hey that's a good example for my .NET COM Interop session @ SWFOX this year :-)

JSON parsing in WWWC is sub-optimal. I only added array support recently (not released) so arrays would always fail - that works now but the parser can't deal with formatted JSON (ie. multi-line breaks etc.). Lack of effective tools in FoxPro to parse make this tough and perf is a problem as well since VFP has no efficient way to parse character by character.

euo
October 04, 2012

# re: Using JSON.NET for dynamic JSON parsing

Hi Rick -
What would you recommend if, say, I wanted to update just a select number of fields received from request.

For example we have these Models:
Album has Id, AlbumName, Artist, Entered, YearReleased, ModifiedDate, AddedDate
Song has Id, AlbumId, SongName, Length, ModifiedDate, AddedDate

Album:
Id= 1
AlbumName= "Dirty Deeds Done Dirt Cheap",
Artist= "AC/DC",
Entered= 01 October 2012,
YearReleased= 1976
AddedDate = 01 October 2012
ModifiedDate = 01 October 2012

Songs:
Id= 101
AlbumId= 1
SongName= "Dirty Deeds Done Dirt Cheap",
SongLength= "4:11"
AddedDate = 01 October 2012
ModifiedDate = 01 October 2012

Id=102
AlbumId=1
SongName= "Love at First Feel",
SongLength= "3:10"
AddedDate = 01 October 2012
ModifiedDate = 01 October 2012

Restrictions to consider:
Entered should never get altered on PUT
AddedDate should never get altered on PUT
ModifiedDate value will be set by yourself explicitly
only fields received from request should be updated

PUT http://localhost/aspnetwebapi/samples/Album/1 HTTP/1.1
Content-type: application/json
{AlbumName: "modified albumname", Artist:"modified artist" , Entered:"2012-12-31" Songs:[ { Id:101, SongName: "modified 101", ModifiedDate:"2012-12-31"},{ Id:102, SongName: "modified 102", AddedDate:"2012-12-31"}]}

what I am thinking of doing is,

public JObject Put(int id, JObject jAlbum)
{
// find the Album
Album myAlbum = // get it from repository

// loop through each fields received
foreach (var item in jAlbum)
{

//update fields that have been received
// find the correct fields through reflection(?);

// for each properties of myAlbum
// if property name equals item.Key, update it but ignore "Entered", "AddedDate", and "ModifiedDate"
myAlbum.<thekey> = item.Value;

// set explicitly
myAlbum.ModifiedDate = Datetime.Now;

// same logic apply for Songs
}
// persist to repository
repository.UpdateOrCreate(myAlbum);
}

the updated album in my repository should be


Album:
Id= 1
AlbumName= "modified albumname" //updated
Artist= "modified artist" //updated
Entered= 01 October 2012 //unchanged
YearReleased= 1976 //unchanged
AddedDate = 01 October 2012 //unchanged
ModifiedDate = 04 October 2012 //updated

Songs:
Id= 101
AlbumId= 1
SongName= "modified 101" //updated
SongLength= "4:11" //unchanged
AddedDate = 01 October 2012 //unchanged
ModifiedDate = 04 October 2012 //updated

Id=102
AlbumId=1
SongName= "modified 102" //updated
SongLength= "3:10" //unchanged
AddedDate = 01 October 2012 //unchanged
ModifiedDate = 01 October 2012 //updated

I can achieve my goal with this approach. But would you recommend it? Is there any better/faster way of doing this?

Thanks,

Raju Golla
January 21, 2013

# re: Using JSON.NET for dynamic JSON parsing

Thanks Rick!

Simple solution to return an Object, which eventually a Json Object. Helped in my ASP.NET Web API service to return Json Object with a single property.

Aviv Roth
June 23, 2013

# re: Using JSON.NET for dynamic JSON parsing

Strangely, the syntax object.property (e.g. 'json.Name') did not work for me at all. Only object["property"] (e.g. 'json["Name"]') seemed to work.

Not only that, but I didn't need dynamics to make object["property"] work. On the other hand, even with dynamics, object.property did not work for me.

Any ideas what I might have forgotten?

Rick Strahl
June 23, 2013

# re: Using JSON.NET for dynamic JSON parsing

@Aviv - Are you sure you're casting to dynamic first? You have to explicitly cast JObject to dynamic:

dynamic jdCust = new JObject();

Aviv Roth
June 24, 2013

# re: Using JSON.NET for dynamic JSON parsing

@Rick:

No dice. Here's my code:
 dynamic tweet = new JObject();
 
 tweet = JObject.Parse(json);
 
 string gender = tweet.demographic.gender;
 Console.WriteLine(gender);


And I get the following error:

"'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'demographic'".

The following works fine:
 var tweet = JValue.Parse(json);
 
 var gender = tweet["demographic"]["gender"];
 Console.WriteLine(gender);


Again, at least I have a workaround, but this dynamics stuff is still a mystery to me. Thanks!

Satish Kumar
July 02, 2013

# re: Using JSON.NET for dynamic JSON parsing

Thanks for a very informative article. It has taught me a new way to parse JSON.

I tested this way against using a strongly typed parsing and I found the dynamic method seems to be taking slower? Could this be right? Or should I check my code again to see if there is something unnecessary I might be doing?

Thanks.

Christoph
August 18, 2013

# re: Using JSON.NET for dynamic JSON parsing

Hi
Test with WebApi was ok, but with WebApi OData, I have problems.
I would like to create dynamic objects with jObject and return these dynamic data.

Has some realized this or some tipps?

Garry @ TriSys
August 20, 2013

# re: Using JSON.NET for dynamic JSON parsing

Should we now (August 2013) be using the new JsonValue from Microsoft or the technique described above?

Rick Strahl
August 20, 2013

# re: Using JSON.NET for dynamic JSON parsing

@Garry - Microsoft officially doesn't use its deprecated, internal Json library anywhere in WebAPI (and other places) anymore. Work on that was discontinued when JSON.NET was added to ASP.NET as a core library. At this point you should use JSON.NET (or other JSON library).

richard
August 20, 2013

# re: Using JSON.NET for dynamic JSON parsing

Having problems with JSON.net - downloaded your example project to make sure it wasn't just me...


VS2012 Winform Windows 8

An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Unknown Module.

Additional information: 'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'AlbumName'

This occurs at "album.AlbumName = "Dirty Deeds Done Dirt Cheap"; " in fragment below

        [TestMethod]
        public void JObjectOutputTest()
        {
            // strong type instance 
            var jsonObject = new JObject();
 
            // you can explicitly add values here
            jsonObject.Add("Entered", DateTime.Now);
 
            // dynamic expando instance you can add properties to
            dynamic album = jsonObject;
 
            album.AlbumName = "Dirty Deeds Done Dirt Cheap";
            album.Artist = "AC/DC";
            album.YearReleased = 1976;


(Also have problems using JSON.Net with HttpClient :

System.MissingMethodException

Method not found: 'Newtonsoft.Json.Linq.JToken Newtonsoft.Json.Linq.JObject.GetValue(System.String)'

.. if you happen to know or can refer me... Thanks, R)

Rick Strahl
August 20, 2013

# re: Using JSON.NET for dynamic JSON parsing

@richard - that code works for me and all tests pass. So there must be something else going on if that doesn't work for you. You sure you're running the project as provided or are you plugging this code in somewhere else?

Y#
November 19, 2013

# re: Using JSON.NET for dynamic JSON parsing

Great article, to give developers a nice overview of the possibilities. Big fan of C# here, but "dynamic" is one of those recent additions to C# that are a bit paradoxical (just IMO, I could elaborate at lengths but that'd be off topic).

Now, and since terseness (to avoid tedious class type mapping between C# and JSON) is one of the obvious and expected frequent use cases, I'm more in favor of keeping type safety (strong typing) while also keeping things short. Here's a small sample:

        public static void RickStrahlsDynJSONTests()
        {
            Console.Clear();
            Console.WriteLine("Rick Strahl's sample");
            Console.WriteLine();
            Console.WriteLine("( @ http://west-wind.com/weblog/posts/2012/Aug/30/Using-JSONNET-for-dynamic-JSON-parsing )");
            Console.WriteLine();
 
            // In the mood for terseness :)
            var Album = new
            {
                Entered = default(DateTime),
                AlbumName = "",
                Artist = "",
                YearReleased = 0,
 
                // As we want an IList<> of songs (another anonymous type),
                // one of our extension methods on System.Type will do the trick:
                Songs = (null as Type).List(new {
                        SongName = "",
                        SongLength = ""
                    })
            };
            // We use "new[] {}" to shape what we're interested in,
            // here by a prototype array of our anonymous type (the one held @ Album, above)
            var albums = new[] { Album }.
                FromJson
                (
                    jsonString, // Don't forget the revivers, to map doubles into ints, and strings into DateTimes:
 
                    Map.Value(default(double), default(int)).Using(
                        (outer, type, value) =>
                                                        ((outer == typeof(int)) && (type == null)) ?
                                                                (Func<int>)
                                                                (() => Convert.ToInt32(value)) :
                                                                null
                    ),
 
                    Map.Value(default(string), default(DateTime)).Using(
                        (outer, type, value) =>
                                                    ((outer == typeof(DateTime)) && (type == null)) ?
                                                                (Func<DateTime>)
                                                                (() => DateTime.Parse(value)) :
                                                                null
                    )
                );
 
            Console.WriteLine("All albums, all songs:");
            Console.WriteLine();
            // Stay terse... however, stay strongly typed, too! :)
            foreach (var album in albums)
            {
                Console.WriteLine("\t" + album.AlbumName + " (" + album.YearReleased.ToString() + ")");
                foreach (var song in album.Songs)
                    Console.WriteLine("\t\t" + song.SongName);
            }
 
            Console.WriteLine();
            Console.WriteLine("First album, first song:");
            Console.WriteLine();
            Console.WriteLine("\t" + albums[0].AlbumName);
            Console.WriteLine();
            Console.WriteLine("\t\t" + albums[0].Songs[1].SongName);
            Console.WriteLine();


More at :

https://code.google.com/p/ysharp/source/browse/trunk/TestJSONParser/BasicTests.cs
;-)

Ajmal
April 05, 2014

# re: Using JSON.NET for dynamic JSON parsing

I am writing a C# wrapper for a RESTful JSON API, and using Json.NET to de-serialize the incoming json to strongly typed object. but a few properties in the incoming json are highly dynamic, it will be some json object with different number and type of properties. My current solution is, I mapped the dynamic json property to JObject in my C# class. Is this a good practice use this, considering JObject depend on a third party library (Anyway Json.NET is a dependency for my library because I am using it for json serialization) . Please advice.

Rick Strahl
April 05, 2014

# re: Using JSON.NET for dynamic JSON parsing

For all intents and purposes, JSON.NET is now a .NET component especially for Web apps. On the Web Stack JSON.NET is a standard added component for any MVC/Web API project, so it's typically available. You need to use some JSON library and JSON.NET certainly is a better choice than any of the native .NET solutions by far, especially for dynamic JSON parsing which isn't supported in any of the native .NET JSON parsers. Microsoft has just about abandanoned the native JSON parses anyway.

With NuGet having an external dependency is much less of an issue these days as you can easily tie dependencies together in source code projects. For compiled project - yes you may have to ship another assembly, but chances are it's already there.

KCS
April 10, 2014

# re: Using JSON.NET for dynamic JSON parsing

I cannot get the dynamic methodology to work with Silverlight (5).

// strong typed instance
var jsonObject = new JObject();

// cast to dynamic to dynamically add/read properties
dynamic album = jsonObject;

album.AlbumName = "Dirty Deeds Done Dirt Cheap"; // WORKS

album.Songs = new JArray() as dynamic; // FAILS

Ryan
October 08, 2014

# re: Using JSON.NET for dynamic JSON parsing

JSON.NET is fine for most JSON serializing when it comes to dynamic objects as long as ALL the properties on the object are dynamic.
If you have an object, say MyClass which implements a DynamicObject

    public class MyDynamicClass : DynamicObject 
    {
        public string MyStaticString { get; set; }
    }


then you try serialize this object you will notice weird behavior
var c = new MyDynamicClass();
c.MyStaticString = "foobar";
 
Console.WriteLine("JSON.NET: " + JsonConvert.SerializeObject(c));


Notice how the MyStaticString property is not there. Not ideal.

Ajay Raval
November 09, 2014

# re: Using JSON.NET for dynamic JSON parsing

Looking for these for Some time now.
Thanks a ton...
+1 for explaination...

Sateesh
November 03, 2015

# re: Using JSON.NET for dynamic JSON parsing

What is the VB.NET equivalent as there is no dynamic keyword.

Gopal
December 09, 2015

# re: Using JSON.NET for dynamic JSON parsing

How do I create JObject inside a JObject ? without using JArray.

for eg.
{
"A" : "a",
"B" :
{ "B1" : "b1",
"B2" " "b2"
}
}

johndoe
January 03, 2017

# re: Using JSON.NET for dynamic JSON parsing

When serializing using dynamic json, is there a way to create a bracket(array) without a name in front of it? [ { level1:[{ [ {test:"test1"}, {test:"test2"} ] , [ {test2:"test1"}, {test2:"test2"} ] }] } ]


Rick Strahl
January 03, 2017

# re: Using JSON.NET for dynamic JSON parsing

@JohnDoe - not inline of an object. That's not valid JSON. Top level arrays (ie. the document root) stars without a label.


Patrick
January 27, 2018

# re: Using JSON.NET for dynamic JSON parsing

I was looking for parsing JSON without creating an entity. Where do I find what I need? Rick's blog of course!


Matt
August 30, 2019

# re: Using JSON.NET for dynamic JSON parsing

How do you use the approach with dynamic when the JSON element is not a valid C# symbol? I have a bunch of code that was using dynamics, but then the format was changed such that some elements are now named things like "j=<".


Rick Strahl
August 30, 2019

# re: Using JSON.NET for dynamic JSON parsing

@matt - you can use the JObject/JToken collection syntax to access values by name.


Simon Jeffs
October 14, 2021

# re: Using JSON.NET for dynamic JSON parsing

Excellent item. I am using it to parse json in to a dynamic object to then be passed to a SQL parameterised query and I get the following error

No mapping exists from object type Newtonsoft.Json.Linq.JValue to a known managed provider native type

JSON:

{
    "sql": "select * from XXXXX where id = @ID",
    "parameters": [
        { 
            "ParamName": "@ID",
            "ParamValue":1
        }
    ]
}

Here is a snippet:

parameters is my equivalent of the songs in the example and is failing on the integer value but it could be an object or anything else

if (parameters != null)
                                {
                                    foreach (var param in parameters)
                                    {
                                        DbParameter p = cmd.CreateParameter();

                                        p.ParameterName = param.Item1.ToString();
                                        p.Value = param.Item2;
                                        cmd.Parameters.Add(p);
                                    }
                                }

                                using (DbDataAdapter da = factory.CreateDataAdapter())
                                {
                                    da.SelectCommand = cmd;
                                    da.Fill(dt);
                                }
                                return dt;

The code is failing on the da.Fill(dt) line with the error. I will not know the type of 'ParamValue' at run time. Am I missing a trick?


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024