Reputation: 11606
I am developing a RESTful web service.
I have a bunch of entity classes (mostly JPA entities, but also other beans).
There are gazillions of object mapping, serialization, binding and whatnot libraries out there. I'm looking for a one that will enable me to:
Serialize the entities to XML and JSON
Serialization MUST support using getters, not only object fields.
It MUST support views. By views I mean a way to specify a subset of the properties of the entity, which are to be serialized. For an example, see Retrieving Partial Resources in the Yahoo! Social Platform API. I also don't want it to recurse indefinitely deep:
The view should define a) properties to be exposed in the entity and b) a view for each of them (if they're entities themselves).
For example, the entity Person
might have views full
and simple
. When requesting a simple
view of a Person
, only properties id
, firstName
and lastName
would be serialized. When requesting a full
view, the properties mother
and father
(which are Persons
themselves) would also be serialized, but only with the simple
view (so it wouldn't recurse to grandparents).
The JSON serialization MUST be "natural", i.e. what would make sense in Javascript. That means I want proper integers, booleans and nulls and I don't want extra object wrappers or something that tries to capture the entire XML Infoset.
For XML, it MUST be possible to configure the serialization to use empty elements for serializing nulls, not XML Schema's xsi:nil="true"
attributes.
Additionally, arrays must be serialized using nested elements so it's possible to differentiate between empty arrays and properties which aren't present in a given view:
Undefined friends
property (not present in view):
<person>
</person>
Empty array, person has no friends:
<person>
<friends></friends>
</person>
Deserialize XML and JSON and merge the data into existing entities
Now this is the difficult part. The next two are connected:
Deserialization of partial objects MUST be possible (analogous to views, but which properties are present is not defined in advance).
Merging into existing properties, not creating new ones.
This is a bit tricky to explain. Most libraries deserialize into Java objects, but at that time, the distinction between an undefined property and a null/empty property (as it exists in Javascript/JSON, XML as described above, PHP, ...) is lost.
When being given this XML:
<person>
<lastName>Bon Jovi</lastName>
<friends></friends>
</person>
and being passed a Person
object, the library should:
person.setLastName("Bon Jovi");
person.setFriends(new ArrayList());
It shouldn't touch the entities firstName
and/or clear it's father
, for example.
Of course with lists this should be more complex. I would expect to configure an id property, by which it would decide whether to update the nested entity or create a new one.
These updates/patches are a reason why the library MUST NOT just return a DTO: because at that time a null
might either mean "unset" or "do nothing".
Well, that's it. I've been saying "MUST" a lot, I realize now :) The library needn't actually provide that, but there must be a way to add the functionality in a clean fashion (= not in a way that would make rewriting everything easier).
Upvotes: 3
Views: 2663
Reputation: 116620
For what it is worth, Jackson has partial update out-of-the-box:
ObjectMapper mapper = new ObjectMapper();
Bean existing = ...;
mapper.updatingReader(existing).readValue(jsonSource);
and it can also convert compatible types (similar to serializing to JSON, reading back to different type).
For XML part you can use JAXB, although it can only complete binding as far as I know.
Upvotes: 1
Reputation: 30652
I don't know of existing libraries that do everything you need, but, assuming you're going to need to implement something:
Writing XML or JSON based on bean properties is pretty simple:
For reading: One approach might be to use existing libs (for JSON or XML) to create objects then deal with merging the properties between objects. The XMLDecoder class can read bean XML (assuming you create it using XMLEncoder). The tricky part to this approach is to know when a value has been "set" to null vs just not been set in the XML. This approach also has the extra overhead of creating a bunch of new objects.
Otherwise, reading JSON or XML is a little trickier, but not too bad
Upvotes: 1