Friday, July 11, 2008

Thought of the week: Fast Food Fun

Thank god it's friday. Right now, all I can think of is:

"I'm on a roll, said the Beef Patty to the Pickle"

So what does it mean? Beats me, but must have some significance, since the phrase started echoing in my otherwise empty head. Maybe I should start collecting whimsical sayings and philosophical musings for a book. Like Ambrose Bierce cross-bred with SpongeBob. Or maybe the other way around.

Yes, it has been a busy busy week, after relaxing but too short vacation. :-)

"Me Too Moment" -> "Build tool choices should not be transitive" (by Steve L)

I usually try to avoid wasting others time by "+1" and "me too" posts. But here's something I feel strongly about: I really really agree in that "Build tool choices should not be transitive". Same can be said about many related issues (should your library dictate logging system choice?), but it's most urgently problematic with build systems. It is also related to "Principle of Concervatism for Foundational Libraries", that is, trying to be cautious about baseline JDK requirements imposed by low-level libraries ("why does JDOM not just require JDK 1.7-pre-alpha so we could use this thingamagic that looks reeeally cool?!?"), to allow applications choose their own upgrade cycles.

Minor update for StaxMate in making: 1.2 with Sjsxp compatibility

It will be a while until StaxMate 2.0 is done, mostly since I have decided that it should offer full support for the new (and still work-in-progress...) Typed Access API. Since this beast will be included in Woodstox 4.0 (as part of Stax2 Extension API, curiously versioned at 3.0), it will be a while until all pieces are in place.

But in the meantime there are smaller (but tasty) fish to fry. For example, while it has been implied that StaxMate ought to work with any old Stax implementation, it really has only been tested on Woodstox. Of other implementations, there is just one that actually matters, Sun Streaming Java Xml Parser (Sjsxp), which is bundled with JDK 6 (and 7, I assume). After some testing, turns out that StaxMate 1.1 almost works with Sjsxp. But not quite. 2 particular fixes were needed to get all unit tests to pass. Given that this was relatively easy to do, and that results are useful (one can test StaxMate using, say, Sjsxp, and upgrade to Woodstox as necessary), I think this might just be the main new thing for StaxMate 1.2 maintenance release; and if other low-hanging fruit are found, there's always possibility of cutting 1.3.

Thursday, July 10, 2008

Jackson with some Objectivity: TIMTOWTDI

(that is: "There Is More Than One Way To Do It", aka "Tim Toady")

Now that Jackson is creeping closer to its 1.0 release, package also contains simple robust functionality to map json data to and from Java objects. To be precise, Jackson actually has not just one way to do it but two ways.

Methods are called "Java type mapper" and "JSON type mapper", although other nicknames can be readily coined. For example: "Poor Man's Objects" (aka "Everything's a Map with numbers, Strings and booleans") and "DOM wanna-be" (or "You Know Tree By Nodes It Has").

Java Type Mapper

This mapper is most similar to other Json mappers that everyone (and their monkey [and monkey's fleas' buddies cousins]) have written. Given Json content you can get Maps or Lists that contain other Maps, List, Strings, wrappers (Integer, Long, Boolean) and nulls. And given Maps, List et al., you can generate Json content. Here's how to use this functionality:

  String jsonContent = "{ \"name\" : \"Jackson\", \"data\" : [ 0, 15 ] }";

JsonFactory jf = new JsonFactory(); // need factory for creating parser to use Map hash = (Map) new JavaTypeMapper().read(jf.createJsonParser(new StringReader(jsonContent))); String name = (String) hash.get("name"); List l = (List) hash.get("data"); int maxValue = (Integer) l.get(1);

And to write content back as Json:

  
  StringWriter sw = new StringWriter();
  JsonGenerator gen = new jf.createJsonGenerator(sw);
  new JavaTypeMapper().writeAny(gen, hash);

Simple enough: values are basic Java data structs and values, and you modify them using normal List.add(), Map.put() methods; iterate over elements and so on.

So why do I call it "Poor Man's Objects"? Because most of the time, Maps, Lists (etc) are used to emulate "real" objects (like beans), with more dynamic access. In some cases this works well (when accessing data in a dynamic context, say, from jsp page); in others it just means losing type-safety without gaining anything. And that is probably the biggest missing piece: ability to map data to and from beans. That is something I hope to address in near future (but probably not within core Jackson project itself).

Json Type Mapper

Whereas the first mapper should be familiar for anyone used to other Java json processing packages, the other alternative should look familiar to those who are working with XML using tree models such as XOM, JDOM, DOM4j, or (unlucky bastards), DOM. This mapper constructs an in-memory tree, represented as set of Nodes traversable using convenient path accessors. One obvious benefit here is that one can eliminate casts: as long as you know type of List entries and Map entry values, you just use appropriate accessor and get results correctly typed (or, type cast exception if type didn't match). So, you will do something like:

  JsonNode rootNode = new JsonTypeMapper().read(jf.createJsonParser(new StringReader(jsonContent)));

// for node traversal, can either use getElementValue(int)/getFieldValue(String), or getPath().
// Difference is dealing with missing elements: getPath() allows for safe de-referencing of missing
// values (essentially creating dummy "missing" node that resolves to N/A value)
String name = rootNode.getPath("name").getTextValue(); // or '.getValueAsText()' for extra safety int maxValue = rootNode.getPath("data").getPath(1).getIntValue();

Looks better? I tend to think so -- while this could be called Poor Man's XPath, I think it reasonably convenient as is. In addition to data extraction as shown, tree can be modified, children iterated and so forth. Beyond explicit traversal using node methods, there are also future plans for implementing JsonPath to be able to use more concise notation. Such implementation could be based on the Json Type Mapper and should be easy to implement.

Which one should I use?

Whichever fits your use case, of course. But what would that be? One way to think about is whether you prefer path-access (json type mapper), or Java container traversal (java type mapper). Or more generally: if you have plenty of Java structs waiting to be thrown around, Java type mapper may be more convenient way to join things together. Especially so when you are actually just generating Json content, and not parsing it. So perhaps it makes most sense to generate Json from java stuff using Java type mapper; but to extract data from Json content using Json type mapper.

Anyway: I am using Java Type mapper at work for freezing/thawing state of a batch processing system (over restarts), but I hope others are using one or both in more creative ways. Please let me know if you do, add a comment here or email me (at yahoo.com, cowtowncoder).



Related Blogs

(by Author (topics))

Powered By

About me

  • I am known as Cowtowncoder
  • Contact me at@yahoo.com
Check my profile to learn more.