OutputFormat=JSON - The Method in the Madness
Here's how I understand it -- the ?ReadViewEntries URL command and the XML it produces came about thanks to the introduction of the Java applets. It was only ever meant for that purpose. However, we - the developers - got wind of it and started to use it for our own devices. If one day the applets finally die the XML they once used will remain as we've now grown to depend on it.
Skip forward quite a few years and, love it or loathe it, we're still using ?ReadViewEntries and in the same old format. A format I've never liked and never been able to use with any degree of success. For years now I've been writing agents simply to output the same XML but in a sane fashion.
If you add OutputFormat=JSON what happens in the backend? Does the server just do an XML.toJSON() transformation on the standard XML that the same request without the parameter would have lead to? You'd think so, but from what I can see I don't think it can be. There are odd differences between the data structure of the two responses. While the XML structure makes sense. The JSON does not. At least not to me anyway.
Well, at least it made no sense until mdm-adph pointed out the method in the madness. Consider the following side-by-side comparison, which is the result of the same request for a view, one in XML and one in JSON (click for full version).
The XML always made sense as there was a single viewentries node, which contained many viewentry nodes, each of which contained many entrydata nodes. In JSON there's one viewentry node that contains all the entries. Similarly there's only one entrydata per document. At first the difference is a source of confusion and mystery, but as mdm-adph pointed out, it's to make a developer's transition from XML easier.
In theory you could get the value of a particular column for a given row using XPath something like this:
"//viewentries/viewentry["+i+"]/entrydata[@columnnumber=" + j + "]/text"
In JSON it would become:
var viewentries = eval("("+JSONFromView+")"); alert(viewentries.viewentry[i].entrydata[j].text[0]);
See how similar the two methods are?! So, that's the theory and, now I'm aware of it, I can kind of see why the JSON is the way it is.
In practice though it's a different matter. For a start, while IE treats 0 as the first node in XPath. The W3C and other browsers use 1. Then there's the simple fact that actually using XPath in JavaScript is nothing short of a nightmare. Cross browser? Don't even go there! If you've ever managed to use Domino's XML with XPath across the browsers you a much better/more patient man than me.
What I'm left wondering is why they even wanted these parallels between the two in the first place. Why go to the bother of structuring the JSON to be like the XML?
Although Domino's JSON is now usable, whereas the XML never really was, I still find it really confusing to work with, which seems to go against the whole idea of JSON. To me there's a sense of them thinking "Hey, this is enterprise-class software, so we need to over-engineer everything!".
What I'm still finding myself doing is creating my own JSON using an Agent. Partly because I still have customers on Domino 6, but also because I just prefer to keep the JSON as plain and simple as possible and in a sensible and readable format. More on that next time.
It's a shame really. My initial excitement at the announcement there would be native JSON output for Views has now passed. As is always the case it's better to do as much as possible on your own. Although I do still, on occasion, use OutputFormat=JSON I just prefer my own way.
Hi Jake, I think the biggest problem is that the structure of the XML and the JSON output is there to describe *any* view with all the possible detail that could be required. If you have a specific application use for a view then you just don't need most of that detail and you can structure it in a nice convenient application specific format.
To make the situation any better would require that a bunch of controls be put in the view design note to describe what formatting you wanted, but that's a lot like just putting JSON into the view output and telling it to render as HTML.
Still if there where specific design controls it would be a whole lot simpler, easy to maintain and provide solutions to corner cases that require agents now.
XML unusable? We found a use for it shaving many hours off of a project by using ReadViewEntries rather than baking custome XML and used the view as a data transport between two applications - one that manages pay station locations (notes) and one that lists the information and maps it (via a third party service) on an ASP.NET website.
It appears perfectly useful when you have a reciever system with robust XML parsing built in. Trying to do the same in the browser I can understand being an issue - but have you considered pairing it with an XSLT?
I'm not saying it's unusable Jerry. Just that to use it cross-browser is a nightmare. Well-formatted JSON is a breeze in comparison.
Jake - I've experienced your same frustration. So I started the RVEX project on openntf.org. If you or anybody cares to contribute, feel free. It's very rough at this point, but it outputs properly next XML or JSON from simple views in a way you might hope they would be exported in the first place. You just add an agent to your application, and then any view can be referenced.
Hi Jake,
I am in the midst of a project where I am using Flex to access domino data. I know you've been getting into Flex lately and I thought you might be interested in this. Also, I am having problems with it as well.
I found a neet library called as3Corelib from the guys @ Adobe.
http://code.google.com/p/as3corelib/
It has some cool utility type code in it. Supposedly it should parse JSON code for you. I thought great. I can reduce some of my overhead rather than calling Domino Webservices I can fetch some data from a view getting at the JSON code.
Ofcourse the first test it doesn't work. I'm hoping your knowledge of JSON and Domino might be able to help?
Here is my code for the flex app. Very simple. If you can dowload the JSON code and check it out I would be forever greatful.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" layout="absolute"
creationComplete="init()">
<mx:Script>
<![CDATA
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import com.adobe.serialization.json.JSON;
private function init() : void
{
service.addEventListener( ResultEvent.RESULT, onJSONLoad );
service.send();
}
private function onJSONLoad(event:ResultEvent):void
{
//get the raw JSON data and cast to String
var rawData:String = String(event.result);
//decode the data to ActionScript using the JSON API
//in this case, the JSON data is a serialize Array of Objects.
var arr:Array = (JSON.decode(rawData) as Array);
//create a new ArrayCollection passing the de-serialized Array
//ArrayCollections work better as DataProviders, as they can
//be watched for changes.
var dp:ArrayCollection = new ArrayCollection(arr);
//pass the ArrayCollection to the DataGrid as its dataProvider.
grid.dataProvider = dp;
}
]>
</mx:Script>
<mx:HTTPService id="service" resultFormat="text"
url="http://YOUR DOMINOSERVER URL HERE/names.nsf/people?ReadViewEntries&outputformat=json"
/>
<mx:DataGrid id="grid" dataProvider="arr"/>
</mx:Application>
Thanks,
STeveR
Hi SteveR,
My guess would be that you can't decode Domino's JSON straight in to a Flex Array as the data in the JSON isn't array-like in the first place. The array-like data is inside the entrydata object within the JSON. I think. You'd have to decode to some "flat" structure and then create an Array from entrydata.
Jake