I'm using json.org JSONObject. I've tried to serialize it to memcache and got the not so cool java.io.NotSerializableException: org.json.JSONObject. Looking at the JSONObject code it seems that it's nothing more then a Map wrapped by JSON logic. Why not make it serializble then?
I would like to be able to store the object into memcache in an easy interface. Is there a similar API implementation of JSONObject that is also serializble. Alternatively, what memcache friendly serialization / deserialization technique do you use ?
Thank you,
Maxim.
JSONObjects are meant be sent as simple strings. So instead of storing the Java serialized form of your JSONObjects you should store the stringified forms.
if you use org.json.JSONObject, it doesn't implement the Serializable interface. For that reason it can't be serialized. Instead, you can put the String version of JSONObject into MemCache.
I have found http://code.google.com/p/json-simple/ to be API compatible implementation of org.json.JSONObject. It does not have all the getDouble, getLong, getJSONArray methods but other then that the concepts are pretty much the same.
It excels over org.json implementation by the fact that it simply extends HashMap for JSONObject and ArrayList for JSONArray making these objects by definition serializble and thus cacheable.
Related
I am currently working on a vertx.io application and wanted to use the provide mongo api for data storage. I currently have a rather clunky abstraction on top of the stock JsonObject classes where all get and set methods are replaced with things like:
this.backingObject.get(KEY_FOR_THIS_PROPERTY);
This is all well and good for now, but it won't scale particularly well. it also seems dirty, specifically when using nested arrays or objects. For example, if I want to be able to fill fields only when actual data is known, I have to check if the array exists, and if it doesn't create it and store it in the object. Then I can add an element to the list. For example:
if (this.backingObject.getJsonArray(KEY_LIST) == null) {
this.backingObject.put(KEY_LIST, new JsonArray());
}
this.backingObject.getJsonArray(KEY_LIST).add(p.getBackingObject());
I have thought about potential solutions but don't particularly like any of them. Namely, I could use Gson or some similar library with annotation support to handle loading the object for the purposes of manipulating the data in my code, and then using the serialize and unserialize function of both Gson and Vertx to convert between the formats (vertx to load data -> json string -> gson to parse json into pojos -> make changes -> serialize to json string -> parse with vertx and save) but that's a really gross and inefficient workflow. I could also probably come up with some sort of abstract wrapper that extends/implements the vertx json library but passes all the functionality through to gson, but that also seems like a lot of work.
Is there any good way to achieve more friendly and maintainable serialization using vertx?
I just submitted a patch to Vert.x that defines two new convenience functions for converting between JsonObject and Java object instances without the inefficiency of going through an intermediate JSON string representation. This will be in version 3.4.
// Create a JsonObject from the fields of a Java object.
// Faster than calling `new JsonObject(Json.encode(obj))`.
public static JsonObject mapFrom(Object obj)
// Instantiate a Java object from a JsonObject.
// Faster than calling `Json.decodeValue(Json.encode(jsonObject), type)`.
public <T> T mapTo(Class<T> type)
Internally this uses ObjectMapper#convertValue(...), see Tim Putnam's answer for caveats of this approach. The code is here.
I believe Jackson's ObjectMapper.convertValue(..) functions don't convert via String, and Vert.x is using Jackson for managing JsonObject anyway.
JsonObject just has an underlying map representing the values, accessible via JsonObject.getMap(), and a Jackson serializer/deserializer on the public ObjectMapper instance in io.vertx.core.json.Json.
To switch between JsonObject and a data model expressed in Pojos serializable with Jackson, you can do:
JsonObject myVertxMsg = ...
MyPojo pojo = Json.mapper.convertValue ( myVertxMsg.getMap(), MyPojo.class );
I would guess this is more efficient than going via a String (but its just a guess), and I hate the idea of altering the data class just to suit the environment, so it depends on the context - form vs performance.
To convert from Pojo to JsonObject, convert to a map with Jackson and then use the constructor on JsonObject:
JsonObject myobj = new JsonObject ( Json.mapper.convertValue ( pojo, Map.class ));
If you have implied nested JsonObjects or JsonArray objects in your definition, they will get instantiated as Maps and Lists by default. JsonObject will internally re-wrap these when you access fields specifying those types (e.g. with getJsonArray(..).
Because JsonObject is freeform and you're converting to a static type, you may get some unwanted UnrecognizedPropertyException to deal with. It may be useful to create your own ObjectMapper, add the vertx JsonObjectSerializer and JsonArraySerializer, and then make configuration changes to suit (such as DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES in Jackson).
Not sure if I've understood you correctly, but it sounds like you're trying to find a simple way of converting POJOs to JsonObject?
So, we have lots of pojos that we send over the EventBus as JsonObjects
I've found the easiest way is to use the vert.x Json class which has loads of helper methods to convert to / from Json Strings
JsonObject jsonObject = new JsonObject(Json.encode(myPojo));
Sometimes you need to add some custom (de)serializers, but we always stick with Jackson - that is what Vert.x is using so they work out of the box.
What we actually do, is provide an interface like the following:
public JsonObjectSerializable {
public JsonObject toJson();
}
And all our pojos that need to be sent over the EventBus have to implement this interface.
Then our EventBus sending code looks something like (simplified):
public <T extends JsonObjectSerializable> Response<T> dispatch(T eventPayload);
Also, as we generally don't unit test Pojos, adding this interface encourages the developers to unit test their conversion.
Hope this helps,
Will
Try this:
io.vertx.core.json.Json.mapper.convertValue(json.getMap(), cls)
I think that using Gson as you described is the best possible solution at the current time.
While I agree that if a protocol layer was included in Vert.x it would indeed be first prize, using Gson keeps your server internals pretty organised and is unlikely to be the performance bottleneck.
When and only when this strategy becomes the performance bottleneck have you reached the point to engineer a better solution. Anything before that is premature optimisation.
My two cents.
You can try:
new JsonObject().mapFrom(object)
I need to deserialize this json
{"dal.device.status":1,"dal.device.UID":"ZigBee:Yale Doorlock:ah.app.3781220503199452-1","service.bundleid":77,"dal.device.driver":"ZigBee","service.id":159,"service.scope":"singleton"}
But I don't how to do since there are pointers in key (e.g. "dal.device.status") I'm using google gson.
I'm able to deserialize this object using C# and Newtonsoft library using ClassAttributes. Is there something similar for java?
First question when seeing properties with dot in them in a json should be "god, oh god, why ? why all this hatred ?"
But if earth is at stake, you can simply deserialize this mess into an hashmap using gson and work from here.
We are using Spring rest template and jackson json provider to serialize/deserialize json. From my services i send a linkedHashSet back which gets converted to a HashSet on the client side when i receive it. Because of this I loose my insertion order of elements.
Is this the default implementation of jackson json provider for Set ? Is there any other way, so it can deserialize to proper implementation? I feel it's gonna be tricky but inputs will be highly appreciated from you guys.
Thanks
You can specify the concrete class for Jackson to use with the #JsonDeserialize annotation. Just put:
#JsonDeserialize(as=LinkedHashSet.class)
On the property's setter.
It all depends on what you ask the result type to be: if ask data to be mapped to a LinkedHashSet, then JSON Array gets mapped to it. If you use a vague type like java.lang.Object (or java.util.Collection), you will get ArrayList for JSON Arrays.
Keep in mind that JSON is data, not objects (by default), so metadata regarding Java types you used is not passed by default. There are ways to do that, if you need it, but usually you will simply need to provide expected type.
I'm looking for a simple json library to convert json-string to Map or a POJO object. I know it's a duplicate, still I got specific requirements:
no weird dependencies like json-lib (why do you need all of them for a simple task?)
use few lines of codes to accomplish it (KISS principle).
I prefer conversion to Map but POJO will be good almost as well.
that's it.
what do you suggest?
Jackson is good, but I think you can also give GSON a try.
It's simple and easy to use. And there is a unit test for converting json string to Map and vice versa.
Check this:MapTest.java
Hope this help you.
Jackson would be best in this case.
I have a rest service returning some data. I use Restlet client api as shown below to access this service. As you can see, it returns org.json.JSONObject. Is there a easy way to map this to the domain object (may be through annotations?) or should I have to write code to create the domain object?
Representation entity = new ClientResource(uri).get();
JSONObject json = new JsonRepresentation(entity).getJsonObject();
May be you can leverage from Gson library which has a function you need:
// Convert JSON into Java object
SomeObj obj = gson.fromJson(jsonObjStr, SomeObj.class)
You can read more here...
While there are decent APIs for easily mapping between Java data structures, e.g., from the JSONObject to your preferred data structure, since the incoming data format is JSON, I'd much prefer to just use a good JSON-to/from-Java API like Jackson. Depending on the preferred transformation details, the solution might be just one simple line of code with such an API.