Scott Hanselman

NuGet Package of the Week #4 - Deserializing JSON with Json.NET

April 01, 2011 Comment on this post [20] Posted in Javascript | NuGet | NuGetPOW | Open Source
Sponsored By

Hey, have you implemented the NuGet Action Plan? Get on it, it'll take only 5 minutes: NuGet Action Plan - Upgrade to 1.2, Setup Automatic Updates, Get NuGet Package Explorer. NuGet 1.2 is out, so make sure you're set to automatically update!

The Backstory: I was thinking since the NuGet .NET package management siteis starting to fill up that I should start looking for gems (no pun intended) in there. You know, really useful stuff that folks might otherwise not find. I'll look for mostly open source projects, ones I think are really useful. I'll look at how they built their NuGet packages, if there's anything interesting about the way the designed the out of the box experience (and anything they could do to make it better) as well as what the package itself does.

Json.NET is a popular high-performance JSON framework for .NET

If you're moving data around on the web, you'll eventually come upon JSON (JavaScript Object Notation) or as I like to call it, XML with curly braces. (Kidding) (No, I'm not kidding, you can easily convert between XML and JSON in most cases)

It's a lightweight data-interchange format. "It is easy for humans to read and write. It is easy for machines to parse and generate." It's also just JavaScript.

image

From JSON.ORG:

JSON is built on two structures:

  • A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
  • An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.

Basically stuff is either a name/value pair, or a list of stuff. That's it. It's great way to push data around, and since it's so flexible and works with JavaScript, it has become THE way to access many popular APIs for sites like Twitter and Facebook.

Json.NET is James Newton-King's excellent library for accessing and working with JSON on .NET. The 4.0 release is cool not only because it's in NuGet, but also because it's currently the best way to deal with JSON data structures on the Windows Phone. Json.NET is notable particularly for James' obsessive focus on performance (check the charts and graphs!) It's also been around FOREVER. I blogged about Json.NET in 2006, in fact.

Inside the Json.NET NuPkg

If you open up the Newtonsoft.Json.4.0.1.nupkg using the NuGet Package Explorer (that's a ClickOnce link, son) I can learn a lot about how James has packaged up his library.

NuGet Package Explorer - Newtonsoft.Json.4.0.1 (15)

First, notice now he's got a number of folders under his /lib folder. I talked about this a little with the last NuGet Package of the Week, but James has taken it to the max. Kudos to him!

With NuGet, you can have one package that includes versions of assemblies for many different Framework Versions. Check the NuGet documentation on Supporting Multiple .NET Framework Versions and Profiles.

James has create a single NuGet package for Json.NET that does the right thing for .NET 2.0, 3.5, 4, SL4, and the Windows Phone 7. Nice.

One thing I think James should add is a Newtonsoft.Json.Sample package per David Ebbo's post "Take NuGet to the next level with sample packages." I found myself wondering where to start with Json.NET as there was no sample code included. No worries, to the cloud web! James has amazing documentation on Json.NET on his site.

Using Json.NET

I've got this silly little site called SmallestDotNet.com that will look at your system using your Browser's UserAgent (and some JavaScript) to determine what version of .NET you have, and suggest the smallest possible download for you to up to date.

NOTE: This SmallestDotNet site was launched in 2008 but was broken on IE9 until my new friend Calinoiu Alexandru Nicolae from Romania (@CalinBalauru on Twitter) volunteered to fix it. Big thanks to Calin for his work on the SmallestDotNet site! Work is ongoing.)

The site also has a simple JSON payload that will give you the correct direct link to the right download for you. I never understood why it was so hard to get a direct download for .NET, so we put it in a basic JSON payload so you could access it programmatically.

The SmallestDotNet JSON payload looks like this. It's not very sophisticated, but it is what it is.

{
"latestVersion": null,
"allVersions": [

],
"downloadableVersions": [
{
"major": 4,
"minor": 0,
"profile": "client",
"servicePack": null,
"url": "http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=5765d7a8-7722-4888-a970-ac39b33fd8ab"
},
{
"major": 4,
"minor": 0,
"profile": "full",
"servicePack": null,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en"
},
{
"major": 3,
"minor": 5,
"profile": "client",
"servicePack": 1,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyId=8CEA6CD1-15BC-4664-B27D-8CEBA808B28B&displaylang=en"
},
{
"major": 3,
"minor": 5,
"profile": "full",
"servicePack": 1,
"url": "http://go.microsoft.com/fwlink/?LinkId=124150"
},
{
"major": 3,
"minor": 0,
"profile": "full",
"servicePack": 1,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyId=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en"
},
{
"major": 2,
"minor": 0,
"profile": "full",
"servicePack": 2,
"url": "http://www.microsoft.com/downloads/details.aspx?familyid=5B2C0358-915B-4EB5-9B1D-10E506DA9D0F&displaylang=en"
},
{
"major": 1,
"minor": 1,
"profile": "full",
"servicePack": 1,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyID=a8f5654f-088e-40b2-bbdb-a83353618b38&DisplayLang=en"
}
]
}

Maybe I can access it with Json.NET? I wonder if it'll be easy or hard. There's a number of ways I can do it. This one uses the JObject "DOM" in JSON.NET:

var client = new WebClient();
client.Headers.Add("User-Agent", "Nobody");
var response = client.DownloadString(new Uri("http://www.hanselman.com/smallestdotnet/json.ashx"));
JObject o = JObject.Parse(response);'
//Now o is an object I can walk around...

Or, I can make C# classes that LOOK like the shape of my JSON payload and deserialize directly into them, which is cool:

class Program
{
static void Main(string[] args)
{
var client = new WebClient();
client.Headers.Add("User-Agent", "Nobody"); //my endpoint needs this...
var response = client.DownloadString(new Uri("http://www.hanselman.com/smallestdotnet/json.ashx"));

var j = JsonConvert.DeserializeObject<SmallestDotNetThing>(response);
}

public class SmallestDotNetThing
{
public DotNetVersion latestVersion { get; set; }
public List<DotNetVersion> allVersions { get; set; }
public List<DotNetVersion> downloadableVersions { get; set; }
}

public class DotNetVersion
{
public int major { get; set; }
public int minor { get; set; }
public string profile { get; set; }
public int? servicePack { get; set; }
public string url { get; set; }
}
}

Now, look at the j variable in this screenshot. How cool is that?

The JSON has deserialized into C# objects in a Watch Window

There's lots of choices on how you want to consume your JSON with .NET.

New Json.NET Features

The new Json.NET is compiled on .NET 4, and includes some really cool dynamic support. From James' blog, see how things used to work, and how the new C#4 dynamic keyword makes working with JSON more fun.

JObject oldAndBusted = new JObject();
oldAndBusted["Name"] = "Arnie Admin";
oldAndBusted["Enabled"] = true;
oldAndBusted["Roles"] = new JArray(new[] { "Admin", "User" });

string oldRole = (string) oldAndBusted["Roles"][0];
// Admin


dynamic newHotness = new JObject();
newHotness.Name = "Arnie Admin";
newHotness.Enabled = true;
newHotness.Roles = new JArray(new[] { "Admin", "User" });

string newRole = newHotness.Roles[0];
// Admin

This is really an amazing open source library and I encourage you to check it out if you're doing anything at all with JSON, and maybe throw JamesNK a few coins for his efforts. Thanks, James!

Another Json Library: JsonFx 2.0

If you're really interested in ways to consume JSON using C# dynamics, also check out JsonFx 2.0 on GitHub or JsonFx on NuGet! This library is extremely easy to use with dynamics.

Check out how this simple code:

dynamic foo = new JsonFx.Json.JsonReader().Read(response);

Gets you this result...note that is a C# dynamic typed object:

JSON deserialized into a DYNAMIC

Very nice. Enjoy!

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
April 01, 2011 13:33
Why not use the built-in JavaScriptSerializer class?
April 01, 2011 15:58
I came here to say what Stefan said. .NET's built in JSON class can do everything you noted above - so why use something else when the functionality needed is already present in .NET?
April 01, 2011 18:16
Excuse my self-promotion Scott :), but the WebClient download and de-serailizing can be done in one call using EasyHttp which is also available on NuGet. Internally I use JsonFx and you can deserialize it to a dynamic or static class:

April 01, 2011 20:31
The built in fuctions don't let you do what JSON.NET lets you do, and by that I mean access JSON as an object or communicate easily with JSON services.

If all you want is the ability to call JSON web services or work with JSON without the baggage of a framework or DLL, I made my own JSON library (it's one file), .JSON.

I created it so I could easily call JSON-enabled web services like StackOverflow, GitHub, or Envato. You can find it on my GitHub account. It's about 500 lines of code you can drag and drop into your app with only one extra reference, System.Web.Extensions for the serialization/deserialization.

I made it super lightweight so I can do:


dynamic[] repositories = JsonService.GetFrom("http://github.com/api/v2/blahblah").repositories;

// get a JSON value
Uri url = repositories.Last().url; // url is a JSON property but gets typed into a Uri class


If you're going to MIX and the Open Source Fest, you can ask me about it.
April 01, 2011 22:12
Stefan and Charlie - The default JSON serializer is much slower than JSON.NET, especially on SL and the phone.
April 01, 2011 22:33
What is Hanselman up to?

What dastardly plan does he have to compromise our computers?

Why does Microsoft's Internet Explorer tell us not to trust his website?

"To help protect your security, Internet Explorer has blocked this website from displaying content with security certificate errors. Click here for options..."
April 07, 2011 18:57
Json.NET rocks. I've started using it on Windows Phone 7 apps and it's a dream. One line to deserialize my calls into a full object graph and one line to serialize it back again into Isolated Storage. No more parsing xml! It also has some cool features like being able to write it out to xml if you want.

One thing to get when working with JSON is JSONView, an add-on for Firefox. Once installed, any JSON url you browse to is displayed in the browser rather than presenting itself to download to a file. Highly useful when debugging your calls or just seeing what the JSON looks like for something.

Someday we'll have the add-on community for IE that FF has. Well, maybe.

https://addons.mozilla.org/en-US/firefox/addon/jsonview/
Bil
April 07, 2011 19:03
One more thing. If you're working with reading JSON it's fine to build your own classes but for a large JSON payload try the JSON C# Class Generator from CodePlex. It's not perfect but I find it useful when I'm dealing with having to build the class heirachy to deserialize JSON. I visit the site with Firefox and the JSONView add-on, copy the payload, paste it into the JSON C# Class Generator and usually go in and just strip down the class to it's minimum. Then a single line of code against Json.NET to deserialize the entire graph. Works great!

http://jsonclassgenerator.codeplex.com/
Bil
April 18, 2011 17:13
Thanks for the link, Bil. I've taken code from the JSON C# Class Generator and put it on the web: http://json2csharp.com

This is a great tool for those of us who are either unable to take advantage of the new dynamic type offered in .NET 4 or wanting the benefits that static typing can provide.
April 20, 2011 21:54
The smallestdotnet site is broken in all my browsers.

Chrome:
I can't tell if you've got .NET installed. Perhaps you don't have .NET installed or perhaps your browser isn't letting me know.


Firefox 4:
Looks like you're running FireFox. That's totally cool, but if you've got a version of .NET earlier than 3.5 SP1, I can't tell if you've got .NET installed from FireFox.


IE9:
Seem you're totally up to date! You've got a full install of .NET 4.0 on your machine. I can't tell if you've got .NET installed. Perhaps you don't have .NET installed or perhaps your browser isn't letting me know. Consider visiting this site using Internet Explorer, which will tell me more about if your system has .NET on it or not.


NB: I have both .NET 3.5 SP1 and .NET 4.0 installed. The Firefox message implies you should be able to detect that.

The IE message is totally bizarre - I'm up to date, but you can't tell if I'm up to date, and I should visit in IE???


And what's up with the validation on this form? I've entered my name, email and webpage, but it keeps telling me, "Please enter your OpenId or your Name, Email and Webpage".
April 20, 2011 22:14
Richard - It's simple, browsers that aren't IE don't report what version of .NET you have. That IE9 one is a bug I think. Send me your UserAgent?
April 20, 2011 23:54
My IE9 UA is:
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)


As mentioned on the IE Blog, IE9 will send the short UA string detailed above without pre and post platform registry value tokens. Websites will continue to be able to get the extended UA string with pre and post platform tokens through the navigator.userAgent property.

My navigator.userAgent string is: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3)
April 20, 2011 23:56
Also, if you only support IE, the message for Firefox is quite confusing:
... if you've got a version of .NET earlier than 3.5 SP1, I can't tell if you've got .NET installed from FireFox ...


Since I have .NET 3.5 SP1 and .NET 4.0 installed, the message seems to imply that you should be able to detect them from Firefox.
April 21, 2011 0:06
Richard - Yes and no. There is an optional Firefox Add-On that some enterprises will install that I can use with Firefox, but maybe 5% of folks have it installed.
April 21, 2011 1:09
So shouldn't the message read, "if you haven't installed this add-on (link), I can't tell if you've got .NET installed from FireFox"?
April 21, 2011 1:15
Agreed. The code is messy and needs a once over. Same with the message.
May 14, 2011 12:12
Scott, thanks so much for this! I was stuck and this helped!
June 12, 2011 19:34
Need to check this out.

Have recently been using the scriptfactory in WCF service to create JSON data / output for consumption with a iphone. Looks like this will be jsut great for dooing the same thing for phone 7.

There is, for those fo you interested a phone lib that does the same for iphone

check out stig brautaset JSON library ( might even be part of ios now )

B,,
July 07, 2011 19:04
I ran across this JSON project http://fastjson.codeplex.com/ , which claims to be the fastest & smallest parser out there. I haven't given it a look yet, but figured it was worth mentioning.
August 09, 2011 14:40
There is another super-lightweight json library called SimpleJson that we had created to work well with Facebook C# SDK (http://facebooksdk.codeplex.com). It is called SimpleJson http://simplejson.codeplex.com/

Unlike most of the json libraries out there, we distribute it as a C# source code SimpleJson.cs rather than a .dll file. It will take around 20k for your dll when you add SimpleJson.cs after compilation. It works on .net2.0+ , sl3+ and wp7+.

And you can actually enable/disable data contract support. And it works well with dynamic too incase you are using .net 4.

Install-Package SimpleJson

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.