Json.NET 6.0 Release 1 - JSONPath and F# Support

JSONPath

Json.NET has supported basic path queries with SelectToken since forever. Json.NET 6.0 supes up SelectToken with full support for JSONPath, an XPath like querying language for JSON.

JObject o = JObject.Parse(@"{
  ""Manufacturers"": [
    {
      ""Name"": ""Acme Co"",
      ""Products"": [
        {
          ""Name"": ""Anvil"",
          ""Price"": 50
        }
      ]
    },
    {
      ""Name"": ""Contoso"",
      ""Products"": [
        {
          ""Name"": ""Elbow Grease"",
          ""Price"": 99.95
        },
        {
          ""Name"": ""Headlight Fluid"",
          ""Price"": 4
        }
      ]
    }
  ]
}");
 
// manufacturer with the name 'Acme Co'
var acme = o.SelectToken("$.Manufacturers[?(@.Name == 'Acme Co')]");
 
Console.WriteLine(acme);
// { "Name": "Acme Co", Products: [{ "Name": "Anvil", "Price": 50 }] }

A SelectTokens (plural) method has been added for returning a range of results from a JSONPath query.

// name of all products priced 50 and above
var pricyProducts = o.SelectTokens("$..Products[?(@.Price >= 50)].Name");
 
Console.WriteLine(pricyProducts);
// Anvil
// Elbow Grease

While LINQ to JSON offers more features and flexibility, JSONPath being string based makes it a good choice for persisting a queries or constructing dynamic queries.

F# Support

Json.NET 6.0 adds support for serializing and deserializing F# discriminated unions. There is nothing you need to do, F# discriminated unions will now Just Work.

type Shape =
    | Rectangle of width : float * length : float
    | Circle of radius : float
    | Empty
 
[<EntryPoint>]
let main argv = 
 
    let shape1 = Rectangle(1.3, 10.0)
 
    let json = JsonConvert.SerializeObject(shape1)
    // {
    //   "Case": "Rectangle",
    //   "Fields": [
    //     1.3,
    //     10.0
    //   ]
    // }
 
    let shape2 = JsonConvert.DeserializeObject<Shape>(json)
 
    Console.ReadKey() |> ignore
    0

Assembly Version Happenings

Json.NET has had a static assembly version since 4.5 to avoid binding redirects. The problem with having a static assembly version is if a strongly named assembly with the same version number is found in the GAC, the GAC version will be used ahead for the /bin version. Some people have been encountering the problem that their applications break when someone else GACs an old Json.NET 4.5 on their server. I’m looking at you .NET CMSes.

The plan going forward is to increase the assembly version with major Json.NET releases. 6.0 Release 1 –> 6.0.0.0, 6.0 Release 2 –> 6.0.0.0, 7.0 Release 1 –> 7.0.0.0. Hopefully this will provide a balance between binding redirects and having the GAC ruin your day.

And The Rest

Tons of smaller features like parsing single line comments in JSON, reading multiple pieces of JSON content from a stream with one JsonReader, obsoleting of bad methods and lots of bug fixes.

Changes

Here is a complete list of what has changed since Json.NET 5.0 Release 8.

  • New feature - Added support for JSONPath
  • New feature - Added support for serializing F# discriminated unions
  • New feature - Added support for deserializing nested DataTables and arrays in DataTables
  • New feature - Added support for reading multiple pieces of JSON with a JsonReader
  • New feature - Added AllowIntegerValues setting to StringEnumConverter
  • New feature - Added Decimal and DateTimeOffset constructors to JValue
  • New feature - Added support for reading JSON single line comments
  • New feature - Improved number parsing error messages
  • Change - Changed assembly version to 6.0.0.0
  • Change - .NET 4 Portable build targets MonoTouch and MonoDroid in NuGet package
  • Change - .NET 4 Portable build targets WP8 and SL5 instead of WP7 and SL4
  • Removed - DefaultMemberSearchFlags on DefaultContractResolver is obsolete
  • Removed - SerializeObjectAsync, DeserializeObjectAsync, PopulateObjectAsync on JsonConvert are obsolete
  • Fix - Fixed JObject ICustomTypeDescriptor properties returning incorrect value
  • Fix - Fixed error when casting dynamic base64 string to byte array
  • Fix - Fixed EntityKeyMemberConverter not using property name resolve
  • Fix - Fixed serializing JValues with readonly JsonConverters
  • Fix - Fixed formatting override on SerializeObject methods
  • Fix - Fixed error when wrapping an exception in a JsonConverter
  • Fix - Fixed using extension data with a non-default constructor
  • Fix - Fixed Uri serialization roundtripping with Uri.OriginalString
  • Fix - Fixed TypeNameHandling.Auto with JsonSerializer.Serialize inside a JsonConverter

Links

Json.NET GitHub Project

Json.NET 6.0 Release 1 Download - Json.NET source code and assemblies

Fixing JArray.GetEnumerator() Method Not Found Bug

Getting this method not found error requires a rare combination of factors. If you haven’t seen it then feel free to ignore this blog post.

tl;dr; just tell me how to fix it

If you’re an end user and you get this error then make sure the version of Json.NET your application is loading is 5.0.8. If you have 5.0.8 in your \bin directory and you still get this error then check the GAC as well and update it if necessary.

If you’re a package author and a user reports getting this error from your code then downgrade the version of Json.NET your package is using to 5.0.4, recompile and release a new version of your package. If you can’t downgrade then another option is to add an IEnumerable<JToken> cast to the erroring foreach loop.

foreach (JToken item in (IEnumerable<JToken>)array)
{
  // stuff
}

Another option is to change the foreach loop to a for loop.

The Cause

In Json.NET 5.0.5 I changed JArray.GetEnumerator’s visibility from interface explicit to public. The side effect of GetEnumerator being public is the C# compiler will no longer add a IEnumerable<JToken> cast to foreach loops. The cast is required when GetEnumerator is interface explicit and is only accessible when the object is cast to IEnumerable<JToken>.

The error then occurs when an application or package that has a foreach loop over a JArray and is compiled with a public GetEnumerator is run using an older version of Json.NET, possible out of the GAC, where GetEnumerator is not public. Because there is no cast to IEnumerable<JToken> then .NET can’t find the GetEnumerator method and an exception is thrown.

Json.NET 6.0 Long Term Fix

Rather than have this bug keep popping up for users I’m going to change JArray.GetEnumerator’s visibility back to interface explicit – the visibility it had in Json.NET 5.0.4 and earlier. Because this is a binary breaking change I’m going to increase Json.NET’s version number to 6.0.

Update: I have left GetEnumerator as public and updated Json.NET's assembly version number to 6.0.0.0 instead.

Sorry about this bug. It has sprung up because of a rare combination of factors and unfortunately Json.NET meets all of them.

Json.NET 5.0 Release 7 – Immutable Collections

Immutable Collections

The biggest new feature in Json.NET 5.0.7 is support for serializing and deserializing the offical new .NET Immutable Collections types.

string json = @"[
  'Volibear',
  'Teemo',
  'Katarina'
]";
 
// deserializing directly to an immutable collection, what sorcery is this?!
ImmutableList<string> champions = JsonConvert.DeserializeObject<ImmutableList<string>>(json);
 
Console.WriteLine(champions[0]);
// Volibear

There is nothing you need to do to make immutable collection and Json.NET work together. Upgrade to Json.NET 5.0 Release 7, add the immutable collections NuGet package to your project and you can start using immutable collections with Web API, SignalR or directly from Json.NET like the example above.

Round-trip Extension Data

Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.

public class CustomerInvoice
{
  // we're only modifing the tax rate
  public decimal TaxRate { get; set; }
 
  // everything else gets stored here
  [JsonExtensionData]
  private IDictionary<string, JToken> _additionalData;
}
string json = @"{
  'HourlyRate': 150,
  'Hours': 40,
  'TaxRate': 0.125
}";
 
var invoice = JsonConvert.DeserializeObject<CustomerInvoice>(json);
 
// increase tax to 15%
invoice.TaxRate = 0.15m;
 
string result = JsonConvert.SerializeObject(invoice);
// {
//   'TaxRate': 0.15,
//   'HourlyRate': 150,
//   'Hours': 40
// }

Using extension data to round-trip JSON like this also means you don’t need to worry about third-party sources adding additional JSON because it will automatically be preserved when serializing/deserializing. Nifty.

If you don’t want extension data serialized (or deserialized) then disable that functionality by setting WriteData and ReadData properties on ExtensionDataAttribute to false.

Bug fixes

A couple of bugs crept into Json.NET after the flurry of releases earlier in the year. I have consulted with other developers and the consensus was that bugs are bad so this release fixes all known bugs.

Changes

Here is a complete list of what has changed since Json.NET 5.0 Release 6.

  • New feature - Added support for Immutable Collections
  • New feature - Added WriteData and ReadData settings to DataExtensionAttribute
  • New feature - Added reference and type name handling support to extension data
  • New feature - Added default value and required support to constructor deserialization
  • Change - Extension data is now written when serializing
  • Fix - Added missing casts to JToken
  • Fix - Fixed parsing large floating point numbers
  • Fix - Fixed not parsing some ISO date timezones
  • Fix - Fixed schema validation of integer value when type was number
  • Fix - Fixed writing of IConvertible values when TypeCode returned was Object
  • Fix - Fixed serializing proxy objects with no default constructor

Links

Json.NET CodePlex Project

Json.NET 5.0 Release 7 Download – Json.NET source code and assemblies

Rich HTML5 Charts everywhere with DevExtreme

The rapid rise of mobile devices has created new opportunities for software developers: applications available anywhere and at any time, but has brought with it new problems: do I need to make a website and then a separate mobile application for every platform?

While iOS, Andriod and Windows Phone all use different programming languages, frameworks and tools for native apps, what is cross-platform between every device is HTML and JavaScript. Not only will an HTML5 mobile application allow us to target every platform, we can also reuse skills and knowledge from traditional website development.

In this blog post I will look at DevExtreme, a cross-platform HTML JS framework for Visual Studio, and in particular DevExtreme’s rich JavaScript charting widgets.

Installation and first impressions

DevExtreme has a great looking custom installer that is impressively simple and easy to use: choose trial installation, customize that install location if you want and you’re done.

After installation is complete you are presented with a dialog that serves as a hub to developers getting started with DevExtreme. Resources available to you include links a number of online demos, demo source code that was installed with DevExtreme and comprehensive documentation.

The online chart demos in the DevExtreme Data Visualization Gallery are particularly impressive. There are over 50 charts and their source code available which I found a great aid when using DevExtreme.

Getting Started

To try out DevExtreme’s charting widgets I’m going to create a simple cross-platform dashboard for the online game streaming website Twitch. My dashboard app will query Twitch’s REST API for data and graph the games being streamed and the number of viewers over time of the most popular streams.

Although I’m building my dashboard using ASP.NET MVC and Visual Studio, DevExtreme is a JavaScript framework and it can be used with any server side language and IDE.

Reference the DevExtreme CDN

The first step is adding the DevExtreme charting JavaScript file to the website. Fortunately DevExpress provides a CDN that hosts the JavaScript file we need.

<script type="text/javascript" src="http://cdn3.devexpress.com/jslib/13.1.5/js/dx.chartjs.js"></script>

The CDN returns a compressed, cached response to keep the website nice and fast.

Creating a Chart

DevExtreme’s data visualization widgets include line, bar, area and pie charts; circular and linear gauges; and range selectors. On the dashboard homepage I will create a pie chart displaying the most popular games being streamed on Twitch.

$("#gamesChartContainer").dxPieChart({
    dataSource: [
        {
            game: "Test game 1",
            viewers: 50,
            channels: 1,
            image: "test-game-1.jpg"
        },
        {
            game: "Test game 1",
            viewers: 50,
            channels: 1,
            image: "test-game-1.jpg"
        }
    ],
    series: [
        {
            argumentField: "game",
            valueField: "viewers",
            label: {
                visible: true,
                connector: {
                    visible: true,
                    width: 1
                }
            }
        }
    ]
});

Call dxPieChart on the element you want the chart to appear in. Options are passed to the chart using a simple JSON object as an argument.

Fetching Data from Twitch.tv

Right now the pie chart is displaying static data. To bring in some real world data we’ll call Twitch.tv’s REST API. Because their API supports JSONP we can call the services directly from JavaScript using jQuery.

var ds = [];
$.getJSON("https://api.twitch.tv/kraken/games/top?callback=?", function (json) {
 
    for (var i = 0; i < json.top.length; i++) {
        ds.push({
            game: json.top[i].game.name,
            viewers: json.top[i].viewers,
            channels: json.top[i].channels,
            image: json.top[i].game.box.large
        });
    }
});

Once you have your data ready just include it in the options when initializing the chart.

Interactive Chart

The DevExtreme chart widgets have extensive options for hooking into client side events. To add a tooltip and click action to each game in the pie chart just wire up some functions to the tooltip and pointClick properties when initializing the chart.

tooltip: {
    enabled: true,
    customizeText: function () {
        var game = ds[this.point.index];
        return game.channels + ' streams, ' + game.viewers + ' viewers';
    }
},
pointClick: function (p) {
    var game = ds[p.index];
    $("#gameContainer").html("<img class='game-image' src='" + game.image + "'/>");
},

Creating a Dynamically Updating Chart

The second chart we’ll create for the dashboard application is an area graph over viewers over time for a video game stream. The chart will start out without any data but every couple of seconds we’ll call a Twitch API to return the viewer count and dynamically update the graph with the new data.

$("#streamChartContainer").dxChart({
    title: "Viewers",
    commonSeriesSettings: {
        type: "splineArea",
        argumentField: "date"
    },
    series: [
        { valueField: "viewers", name: "Viewers" }
    ],
    argumentAxis: { valueMarginsEnabled: false },
    legend: { visible: false },
    animation: { enabled: false }
});

Note that no data source has be included in the code above. Data will be retrieved from the Twitch API and set against the chart dynamically.

var dataSource = [];
 
function getStreamData() {
    $.getJSON("https://api.twitch.tv/kraken/streams/" + name + "?callback=?", function (json) {
 
        var viewers = json.stream.viewers;
 
        dataSource.push({
            date: new Date(),
            viewers: viewers
        });
 
        $('#streamChartContainer').dxChart('option', 'dataSource', dataSource);
    });
}
 
setInterval(function () {
    getStreamData();
}, 5000);

Every 5 seconds the browser will poll the server for the current viewers, add the count and date to the data collection and then update the chart with the data collection as an argument.

Wrapping Up

I found the chart widgets in DevExtreme to be fast to setup and easy to use while still offering a lot of power for customization.

My small application has barely scratched the surface here of what the chart widgets offer, let alone the other features included in DevExtreme. If you’re looking to building a cross-platform multi-device application then DevExtreme is definitely worth a look.

 

Click here to download the Twitch Dashboard application source code

 

Disclosure of Material Connection: I received one or more of the products or services mentioned above for free in the hope that I would mention it on my blog. Regardless, I only recommend products or services I use personally and believe my readers will enjoy. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: Guides Concerning the Use of Endorsements and Testimonials in Advertising.