Sunday, June 13, 2010

JSOG - JavaScript Object Graph

So I had a project where I was creating a user preferences service. Because the environment in which the preferences service was to be operating is so chaotic (lots of changes are expected), I decided to use JSON as a way to store the user preferences. The service is a glorified document database, if you will.

Now, working with JavaScript objects and arrays in JavaScript is pretty easy. There's a lot of implicit coercion taking place, it's a dynamic language after all. That doesn't translate to Java very well, however. I looked at JSON-lib, FlexJSON, Jackson, and the library. None of them provided the functionality I was looking for. I want to easily navigate a JSON object graph, and manipulate the values within.

Let's look at my particular use case for example. I had a JSON object for a user. Within that JSON object, I basically had the following: (Formatted for readability)

"services": {
"xyz": {
// XYZ specific preferences

Except since things are so chaotic, I don't know if the "services" node exists, or if "xyz" exists.

I'll demonstrate with Jackson here, but the process is basically the same for the other libraries I looked at.

In this example, we create the object from scratch:

ObjectNode prefs = nf.objectNode();

ObjectNode services = nf.objectNode();
prefs.put("services", services);

ObjectNode xyz = nf.objectNode();
services.put("xyz", xyz);

xyz.put("foo", "bar");

What does that same code look like in JSOG?

JSOG jsog = JSOG.createObjectNode();
.put("foo", "bar");

A little more straight forward, but Jackson wasn't that bad. What about a more complex example?

Instead of creating everything from scratch, what if we need to parse the existing preferences and add a value? If the JSON object doesn't contain "services", or "xyz" (which we're not sure of), we need to create those nodes.

Let's parse a string, empty in this case, and build up the same object, and add a value to "xyz" called "baz" with value 42.

Here's what you're facing with Jackson:

ObjectMapper om = new ObjectMapper();
JsonNodeFactory nf = om.getNodeFactory();

// Parse the JSON string
JsonNode json = om.readTree("");

// Get or create the prefs container object
ObjectNode prefs;
if (json.isObject()) {
prefs = (ObjectNode) json;
} else {
prefs = nf.objectNode();
json = prefs;

// Get or create the services object
JsonNode servicesNode = prefs.path("services");
ObjectNode services;
if (servicesNode.isObject()) {
services = (ObjectNode) servicesNode;
} else {
services = nf.objectNode();
prefs.put("services", services);

// Get or create the xyz object
JsonNode xyzNode = services.path("xyz");
ObjectNode xyz;
if (xyzNode.isObject()) {
xyz = (ObjectNode) xyzNode;
} else {
xyz = nf.objectNode();
prefs.put("xyz", xyz);

// Set the value
xyz.put("baz", 42);

And here's JSOG doing the same thing:

JSOG jsog = JSOG.parse("");
.put("baz", 42);

Now we're talking! JSOG pulls off in 5 clean, clear, concise lines of code what took Jackson 38 LOC to do. JSOG does the implicit object creation or coercion for you, and to make things even easier, you get builder-style syntax!

I want to point out that I'm not picking on Jackson here, this is a failing of all the libraries I looked at. I think Jackson is actually one of the easier libraries to use, which is why I chose to use it for JSOG's serialization and deserialization.

JSOG is Unlicensed. I've committed it to the public domain. I would love to see JSOG or an equivalent find it's way into each JSON library.

Visit the JSOG site, hosted on and give it a whirl. I suspect people working with CouchDB will *really* appreciate JSOG.


cowtowncoder said...

Thank you for sharing this! Many good ideas, it is good to see people working to improve existing tools, try out new approaches.

Jeff Rodriguez said...


JSOG has a *lot* more features now, they're just not very well documented. I need to get on that ;)

Perhaps another blog post in the mean time..