Reputation: 101
Just started writing some code with the JSON reference library (http://docs.oracle.com/javaee/7/api/javax/json/package-summary.html), and run into a simple problem. With a simple but "ugly" solution.
JsonObjects are 'immutable', despite being backed by a Map class, this means I shouldn't modify them.
I want to construct an object very dynamically, say, take an array and add an element to it, a full "read/write" model.
And yet the JsonObjectBuilder appears to implement a "write only" interface - you can put things in there but you can't ever read them (doesn't subclass map or anything?), so if you put an ArrayBuilder in there, you have to keep track of that if you later want to add to it (as there's no way of 'reading' the array builder back out and ...)
So there seams to be two interfaces, one is read only, and one is write only, and the only conversion possible is write-only to read-only, no way back, and no way to read/write a JSON structure.
I feel like I'm missing something very obvious...
The obvious "dirty" solution is of course to store the data in my own structure and then convert it to JSON builder at build time, tho this doesn't really help with the receiver of the JSON that needs to modify it and pass it on. A two way interface between my object and its, or a converter that converts read only json's (recursively) back to builders and modifies it in the process...
What am I missing? Why do I seem to have to build my own representation of the JSON and stream it in and out of RO / WO models?
(yes, i did try googling, nothing i came up with was helpful, which further confused me...)
Upvotes: 0
Views: 371
Reputation: 19583
Yes, the JsonObjectBuilder
is used to write all the data you want finalized in a JsonObject
. When you have built the JsonObject
, you will most likely want to serialize him for transmission over HTTP by calling his toString()
method. Then on the other end, if the receiver is a Java VM you would most likely want to use a JsonReader
and begin reversing the process.
I think that the thing you "miss" could be a flaw in your design. Why would another entity need to mutate what has already been written to the JsonObjectBuilder? Wouldn't that mean that your first entity has failed his task?
The JSON API closely resembles how I build my own builder classes. They expose only setter methods, not getters. That is what the end product is built for. The state/value of fields has already been brought to the builder from an external source. Thus we could for most part safely assume that there is "no need" for getters. If we add getters too, they will pollute the API making it twice as big. My builders won't even allow consecutive calls to the setters, instead they throw an IllegalStateException
if someone tries to put in a value into a field that has already been written to. Trying our utmost best to keep objects immutable is a golden rule for thread safety. Simply put it, you need no synchronization or other concurrency mechanisms for immutable objects. Builders is often a chief design pattern to achieve immutability.
Correct me if I am wrong, but isn't the JSON object you're trying to build already backed by a domain model? Say you have a Person class and you want to stringify him using JSON syntax? Well in that case, you shouldn't need to build the JSON string until he's ready to be dispatched somewhere [remotely]. Or as you're kind of saying yourself:
The obvious "dirty" solution is of course to store the data in my own structure and then convert it to JSON builder at build time [..].
That is no dirty solution at all. The receiver receives a String
and need to parse that String into his own domain model, do whatever he like to with that object, and perhaps stringify the object again before dispatching him somewhere else to a third receiver.
If the receiver resides in the same Java VM, then why would you need to use JSON at all?
I feel I might have not been of much help to you, but if so, please update your post and describe your problem a little bit more detailed and I'll get back to you with my thoughts on that.
Upvotes: 1