Moo-able Type for Cowtowncoder.com

Tuesday, March 03, 2009

Saving Software Developers from Franken-JSON

1. The Setup

When it comes to using JSON for
communication, developers often get bait-and-switched by existing
frameworks, most of which are designed to use xml as the underlying data
interchange format. Spiel usually goes along these lines:

Want to use JSON?

We can help with that!

Just need to use a little thing called convention

which allows us to use our existing system as is

and things will work just fine

don't you worry little coder

Well, except that the "little thing" turns out to be this ugly
contraption that mangles clean Json into something that is technically
still Json content, but just barely so: in reality it's just a bit of
spit and polish to mask underlying xml structure. Sort of like those
human masks on lizards on that ancient TV show ("V"). And such systems
likewise require similar bastardization as input.

For one example of such convention, consider Badgerfish
(which is not the only choice; there are other variants such as
"mapped").Resulting Json content is generally along the
lines of "only-mother-could-love" ugliness: for example let's consider
how a simple Bean would get transformed to "JSON" using this convention.Given
a bean like:

class Person { int getAge(); String getName();}

we would get xml like:

<person> <age>37</age> <name>Joe Blow</name></person>

which would be ok as xml, but would then be mapped to "Json" that looks
something like:

(if you are lucky -- number may or may not look like one; and String
that looks too much like a number may become one... after all, XML
content usually has no such type information)

instead of what you might expect:

{
"age" : 37, "name" : "Joe Blow"}

Like it? Me neither. And it gets even worse if you plan to use things
like Lists, and some combinations are just illegal (Lists of Lists).

2. Why oh why?

Now: there are legitimate reasons to use such mapping conventions:
sometimes one has to do convert things into other uglier things for
interoperability reasons. Legacy systems may be practically
unmodifiable, and require certain kinds of butt ugly inputs. There are
also plenty many XML-based systems, frameworks and protocols in
existence.So it is natural to consider easy ways to make use of this
existing infrastructure. And finally, most JSON tools up until fairly
recently seem to be have been made by Santa's elves, and
professional-grade tools are somewhat of a recent development.

But the fundamental problem is this: if you need and/or want to use XML,
use it. And if you do use XML, what purpose would JSON serve in the mix?
It's like connecting a Porsche engine to a Jugo transmission system, all
enclosed in a Ford Pinto chassis. Or, brains of mr. Ab Normal within
poor old Frankenstein's skull.And even within Javascript execution
environment, DOM-based xml trees have been available almost since dawn
of the Interweb -- you can already use XML easily. So to have some
actual benefits, JSON should be accessed natively, au naturel. Not as a
round peg slammed through the square hole.

3. Solution

But why all these ugly workarounds? Perhaps framework builders do not
see much need for JSON, and just want to be buzzword compliant? Or
perhaps they have been turned off by earlier crop of toy JSON tools.Whatever
the underlying reason is, most seem to just offer the backhanded
convention-ridden route.

But here is some good news. Jackson
project can help JSON-craving developers; now with a Content conversion
provider that is designed to work with any compliant JAX-RS
implementation: JacksonJsonProvider
is the thing you need to hook up to your JAX-RS
implementation (tested with Jersey,
as well as RESTEasy). You can
download the jar here
(look for "jax-rs" jar; uses core and mapper jars).

So what is this mysterious provider? It is the thing that JAX-RS needs
to know how to convert from Json to POJOs and back. And as long as you
hook this up as a resource you only need to indicate input and output as
being Json (with @Consumes and @Produces resource annotations, or by
client provided MIME headers that indicate the same) and it will all
actually work out, and quite as you would expect it to.

The only remaining detail is that of hooking things up. One way is to
write a simple servlet: here's one way to do that: