Discussions

Hi all,
I'm working on an ExtJs app, and I have to find a way to read and write JSON in Java. However, there are a few implications, and I'd like to ask what solutions are available before I build my own :)
I have found the following existing solutions:
FlexJSON (http://flexjson.sourceforge.net/)
XStream (http://xstream.codehaus.org/json-tutorial.html)
Jackson (http://jackson.codehaus.org/)
There may be others for sure. These are the requirements:
Serializing to JSON
===================
- It must work with hibernate loaded objects
(Jackson throws an error when trying to serialize a lazy-loaded one-to-many relationship: Not that it's not loaded but that there's no serializer for the CGLIB wrapper). I know it's hard to detect whether or not a lazy field has been loaded, but then:
- I'd like to be able to omit certain fields, preferably without using annotations.
XStream has an omitField(..) method, very nice.
(While serializing a user object, I'd like to be able to exclude the password field, or some lazy loaded big text fields, but not always: Some controller may be specially there to serialize that big text field :)
- I'd like to be able to use aliases for fields so I can rename my fields, just like I can change the name of a field in the database using the @Column(name="...") annotation.
FlexJSON and XStream have a lot of options, and seem good candidates. Because of the Hibernate CGLIB error, Jackson fails IMHO.
Deserializing from JSON
=======================
Here's my (simplistic) spring controller:
@RequestMapping(value="/user/save.htm", method = RequestMethod.POST)
public ModelAndView save(@RequestParam String rows, HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = (User)jsonSerializerService.deserialize(User.class, rows);
User savedUser = userRepository.get(user.getId());
copyNonEmptyProperties(User.class, user, savedUser );
userRepository.saveOrUpdate(savedUser);
...
return < a ModelAndView >
( All business model checks are omitted )
The main problem here is that my JSON looks like
{ id: 1, name:"John Doe", role_id: 5 }
So there's no root; XStream can't handle this natively: I have to rebuild the JSON and prepend null }
because XStream needs a root :(
The other problem here is that my javascript app only returns the fields that have changed. Of course I could change that and always send the complete record, but that's not an elegant solution, is it?
That's where the copyNonEmptyProperties(..) comes in, for which I do need an implementation yet :)
From the site, I understand that Jackson read json and put it into a hashmap, see Sample Usage: Data Binding ("untyped") on their documentation page.
That would allow me to iterate over all properties posted and set them by myself.
The last problem when reading JSON is the role_id field. In the business model, the user has a getter/setter, typed as a Role object.
But in the user interface, it's a combo with id/name pairs, of which the JSON deserializer doesn't know about.
So I need to be able to configure something that lets me 'translate' the role_id : 1 into getting and setting a Role object (from the database/hibernate).
Conclusion
==========
Jackson might be appropriate for reading JSON, and FlexJSON and XStream for writing JSON. But I'd like to use a single and more flexible library for serializing/deserialing JSON.
So the question is, what do you use and does it meet the requirements written above?
TIA
Ronald

Ronald,
I use Stringtree JSON ( http://www.stringtree.org/stringtree-json.html ) as my general-purpose Java JSON reader/writer. It's not exactly what you have described, but the code is small enough and simple enough that it seems a good base to start from.
If you haven't already found it, there is a list of JSON implementations at the bottom of the page at http://json.org/ which links to several Java implementations including Stringtree JSON.
As an aside, You don't really make clear in your original post how set-in-stone your particular usage of JSON might be.
I have found over the course of several projects that attempting to convert domain objects directly to/from any external representation (be it JSON, XML, or some binary or custom format) is usually a step too far. Inevitably the conversion code becomes bogged down in special case-processing and soon becomes brittle and proprietary.
A more robust solution might be to use a "soft" layer (such as Maps and Lists of Objects) between your "hard" domain objects and the equally "hard" external representation.
For example:
To send data
domain objects -> special processing (in your case omitting and/or renaming fields etc.) -> Map of Objects/Lists/Maps etc. -> standard and simple JSON serializer -> external JSON text
To recieve data
external JSON text -> standard and simple JSON deserializer -> Map of Objects/Lists/Maps etc.-> special processing (in your case updating changed fields etc.) -> domain objects
With this technique, the processing is nicely separated and maintainable. If you use Spring or any other injection approach, the conversion strategy can easily be configured on deployment or at run-time. As a benefit, if you change your mind and choose a different external format (XML, for example), only the serialization needs to be swapped out; the special processing remains unchanged.
If this seems like an interesting approach and you would like any more detailed discussion, please feel free to connect with me on LinkedIn and/or contact me direct.
Frank.
http://blog.punchbarrel.com/

Hi Ronald.
One question regarding Jackson: did you try asking your question (wrt Cglib) on the user list? One problem (http://jira.codehaus.org/browse/JACKSON-53) regarding Cglib was resolved earlier, and there is good chance that if there are remaining problems, they could be addressed.
But that can only be done if problems are reported.
Other than that, like other poster suggested, about all JSON packages allow you to work with "untyped" objects (Maps, Lists); including StringTree, json-lib, json-utils, stringtree, Jackson etc. etc.

TechTarget provides technology professionals with the information they need to perform their jobs - from developing strategy, to making cost-effective purchase decisions and managing their organizations technology projects - with its network of technology-specific websites, events and online magazines.