So I began to look at how one would go about attaching a JSON-Schema grammar of a JSON document in a WADL description of a service. This isn't a specification yet; but a proposal of how it might work consistently.
Now I work with Jersey mostly, so lets consider what Jersey will current generate for a service that returns both XML and JSON. So the service here is implemented using the JAX-B binding so they both use a similar structure as defined by the XML-Schema reference by the include.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <application xmlns="http://wadl.dev.java.net/2009/02"> <doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 1.16-SNAPSHOT 10/26/2012 09:28 AM"/> <grammars> <include href="xsd0.xsd"> <doc title="Generated" xml:lang="en"/> </include> </grammars> <resources base="http://localhost/"> <resource path="/root"> <method id="hello" name="PUT"> <request> <representation xmlns:m="urn:message" element="m:requestMessage" mediaType="application/json" /> <representation xmlns:m="urn:message" element="m:requestMessage" mediaType="application/xml" /> </request> <response> <representation xmlns:m="urn:message" element="m:responseMessage" mediaType="application/json"/> <representation xmlns:m="urn:message" element="m:responseMessage" mediaType="application/xml" /> </response> </method> </resource> </resources> </application>
So the first thing we considered was re-using the existing element property, which is defined as a QName, on the representation element to reference an imported JSON-Schema. It is shown here both with and another an arbitrary namespace to it can be told apart from XML elements without a namespace.
<grammars> <include href="xsd0.xsd" /> <include href="application.wadl/responseMessage" /> </grammars> <representation element="responseMessage" mediaType="application/json"/> Or xmlns:json="http://wadl.dev.java.net/2009/02/json" <representation element="json:responseMessage" mediaType="application/json" />
The problem is that the JSON-Schema specification as it stands doesn't have a concept of a "name" property, so each JSON-Schema is uniquely identified by it's URI. Also from my read of the specification each JSON-Schema contains the definition for at most one document - not the multiple types / documents that can be contained in XML-Schema.
So the next best suggestion would be to just use the "filename" part of the URI as a proxy for the URI; but of course that won't necessarily be unique. I could see for example the US government and Yahoo both publishing there own "address" micro format.
The better solution to this problem is to introduce a new attribute, luckily the WADL spec was designed with this in mind, that is of type URI that can be used to directly reference the JSON-Schema definitions. So rather than the direct import in the previous example we have a URI property on the element itself. The "describedby" attribute name comes from the JSON-Schema proposal and is consistent with the rel used on atom links in the spec.
xmlns:json="http://wadl.dev.java.net/2009/02/json-schema" xmlns:m="urn:message" <grammars> <include href="xsd0.xsd" /> </grammars> <representation mediaType="application/json" element="m:responseMessage" json:describedby="application.wadl/responseMessage" />
The has the secondary advantage in that this format is backwardly compatible with tooling that was relying on the XML-Schema grammar. Although this is probably only of interesting to people who work in tooling / testing tools like myself.
Once you have the JSON-Schema definition then some users are going to want to do away with the XML all together, so finally here is a simple mapping of the WADL to a JSON document that contains just the JSON-Schema information. It has been suggested by Sergey Breyozkin the JSON mapping would only show the json grammars and I am coming around to that way of thinking. I would be interested to hear of a usecase for the JSON mapping that would want access to the XML Schema.
{ "doc":{ "@generatedBy":"Jersey: 1.16-SNAPSHOT 10/26/2012 09:28 AM" }, "resources":{ "@base":"http://localhost/", "resource":{ "@path":"/root", "method":{ "@id":"hello", "@name":"PUT", "request":{ "representation":[ { "@mediaType":"application/json", "@describedby":"application.wadl/requestMessage" } ] }, "response":{ "representation":[ { "@mediaType":"application/json", "@describedby":"application.wadl/responseMessage" } ] } } } } }
I am currently using the mime type of "application/vnd.sun.wadl+json" for this mapping to be consistent with the default WADL mime type. I suspect we would want to change this in the future; but it will do for starters.
So this is all very interesting but you can't play with it unless you have an example implementation. I have something working for both the server side and for a Java client generator in Jersey and wadl2java respectively and that will be the topic of my next post. I have been working with Pavel Bucek on the Jersey team on these implementations and the WADL proposal, thanks very much to him for putting up with me.
2 comments:
Hi Gerard,
thanks for all the great work you did on the jersey and wadl code.
I developed a demo Restful service on webLogic 12.1.2 which some operations which uses jsonpadding for JQuery and some returns a List of objects.
I want to consume this service and for this I will use the WADL.
With this I got two problems with the WADL
first the jsonpadding operations are not in the xsd0.xsd. Can this somehow be solved.
and Second the list of objects is displayed in the schema as a single object Employee instead of Employees with 1 of many Employee
Thanks
Edwin,
Well the Jersey bods did all the real work. :-) I suspect your problem is that you are using List rather than a collection object.
For various reasons List is a bad idea when using XML, in particular because pluralization is US only and namespaces won't match, so if you can create a simple @XmlRootElement that contains a list of your elements this should fix your WADL.
Cheers,
Gerard
Post a Comment