Using JSON Light in SharePoint Server 2013

​One of the irritations of using the SharePoint REST API was that to get JSON returned instead of XML you had to specify "odata=verbose" in your accept header. This means you have to set up your AJAX request in a slightly more complicated way, for example you can't use the handy jQuery getJSON method because it doesn't give you an opportunity to set the headers. Instead you have to use something like:

$.ajax({

url: encodeURI("http://litvs13/_api/web/title"),

headers: {

accept: "application/json;odata=verbose"

}

}).done(function (data) {

$("#output").text("Site title: " + data.d.Title);

}).fail(function (msg) {

$("#output").text("Request Failed: " + msg);

});

This is a bit of a pain, especially as many published samples based on the SharePoint 2013 beta release used the simpler $.getJSON, and of course didn't work against the release version of SharePoint 2013. It also means we can't use the more compact JSON Light returned by default with OData 3. This wasn't a bug; it was simply that the OData standard was revved at the same time that SharePoint was released and Microsoft did the right thing in requiring the "verbose" flag to indicate that only OData 2 was supported. By the way, it also gives a useful error message in the response if you get it wrong: full marks.

Sports Car


So it was with great excitement that we learned that OData 3 support, along with all the different metadata formats was to be included with SharePoint 2013 Service Pack 1. In the fix list you find KB2817429 "Minimal and no metadata are now enabled as supported JSON formats". This suggests an upgrade to OData 3.0 standard and in fact if you make a metadata request you now get a response that has a DataServiceVersion of 3.0. So far so good. You would therefore expect a request with an Accept header of "application/json;odata=minimalmetadata" or "application/json;odata=nometadata" or just "application/json" to return lightweight OData3 style JSON. And in fact if you make a request against SharePoint Online (Office 365) everything works as advertised which is great.

But if you make the same request against an “on-premise” test farm with SP2013 and SP1 you don't get JSON, or even an error, you get XML (Atom) returned instead. Prior to SP1 we got a 406 error. You can even put garbage in the header, e.g. odata=foobar, and get the same result. Using the original "application/json;odata=verbose" still works, of course. At this point you are probably wondering if JSON Light was actually implemented in Service Pack 1.

Solution

The solution is now posted to Technet. You need to run the script in the article which adds some assembly references to the web.config (specifically Microsoft.Data.Edm, Microsoft.Data.Odata, Microsoft.Data.Services, Microsoft.Data.Services.Client and System.Spatial). These are required to support OData 3 and JSON Light and are not added by default. I would recommend the GUI version of the WcfDataServices.exe installer (remembering to check the GAC option) as the command line returns immediately and you have no feel for progress of the installer, which can take a couple of minutes. You might conclude that it hasn’t worked when it is in fact still running.

One problem I found is that for some reason after installing WCF Data Services and running the JSON.ps1 script, the REST endpoint was completely broken (error log showed it couldn’t find the DLLs for WCF 5.0). I had to run the WcfDataServices.exe installer again to “Repair” WCF Data Services. I also had to do an IISRESET, presumably to reset the DLL bindings. After this everything worked. Not sure if this is something peculiar to my environment – I am using Windows Server 2012 and I have Visual Studio 2013 installed which might be a factor (see http://blah.winsmarts.com/2014-1-VS2013_and_SharePoint2013.aspx).

So a sequence that worked for me was to run WcfDataServices.exe (5.6 version), Options – install to GAC. After it finishes, run WcfDataServices.exe again clicking on “Repair”. Then run JSON.ps1 to update web.config.​

After that you can get rid of the "odata=verbose" qualifiers on your accept headers or pick from a number of supported OData formats. More importantly you can streamline your network traffic by using the more compact JSON Light format, but don't forget that the format is slightly different (no more "d" wrapping element for example). In my opinion it is worth the effort because the JSON Light payloads are significantly smaller and more efficient.