I have an Object that is reference by two other Objects
I use Jackson to serialize my objects but have found my shared object is duplicated rather than reference.
The reason is as I understand that Jackson can only serialize by value and not by reference.
I have unsuccessfully looked around for some recommended solution.
Any and all help is appreciated.
current Jackson Lib 1.8.3
Well time passed and Jackson 2.0 is out. Here is the requested feature ! I answer this so people like me coming after know its available
https://github.com/FasterXML/jackson-docs/wiki/Presentation-Jackson-2.0
Currently (1.9) you would have to write custom serializer, deserializer, to handle this. There is no out-of-the-box support for handling object identity.
Of Java frameworks the only one that I know to support object identities is XStream.
For what it is worth, there is a long-standing feature request for Jackson to add support. And there is reasonable chance this gets worked on for 2.0. But even if it will be, it'll take a while (a month or two).
UPDATE (April 2013): As per the other accepted answer, this feature -- #JsonIdentityInfo -- was indeed included in Jackson 2.0, and is available. No need for custom (de)serializers.
Related
A JsonObject can be transformed into it's corresponding class instance via:
Pojo pojo = JsonbBuilder.create().fromJson(jsonObject.toString(), Pojo.class)
However, it seems to be inefficient to use jsonObject.toString() as a String is an other intermediate representation, that contains the same information. I need to transform the jsonObject before the object binding. So is there a more efficient way to achieve the binding from a JsonObject?
(Note I want to implement with Java EE 8 standards, so Gson and Jackson is not an option, but may be concepts of it). There is currently not answer in the Yasson group so hopefully, someone finds this. Michael Schnell also proposed a JsonStructure binding, but there is no solution yet too.
It is not possible with the JSON-B 1.0 standard to convert JSON-P object <--> POJO. However, enough people have asked for it that it's certainly something we will consider for the next version of JSON-B.
In the meantime, converting to String or using a custom adapter is your best option.
If you are concerned about performance with JSON-B, the #1 thing you can do to improve JSON-B performance is cache the instance of Jsonb, namely, don't call JsonbBuilder.create() each time you need to call to/fromJson, because all of the annotation scanning and class parsing happens upon creation of the Jsonb instance.
Update (June 2019):
Although there is still no JSON-B standard way of doing this, the JSON-B reference implementation, Eclipse Yasson, has added support for this on the org.eclipse.yasson.YassonJsonb interface in this PR. Hopefully this function will get included in the next version of the JSON-B spec.
By necessity, I need to upgrade from Jackson 1.x to 2.x. After reading the notes on the release, I thought it would be fine to upgrade, so long as I made the necessary code changes:
http://wiki.fasterxml.com/JacksonRelease20
However, I realized after-the-fact that I still need to be able to deserialize data serialized with 1.x versions in the event that we have pre-upgrade data data flowing back into the service, which is guaranteed to happen.
Is Jackson 2.x suited to this or not? I understand that 2.x requires recompile, but can it still handle the old serialized format?
So, your case is that data serialized with Jackson 1, will be read by Jackson 2, this shouldn't be a problem at all, since both understand JSON format.
There is a possibility you have customizations based on annotation and hierarchies, even if this is the case, almost everything is supported in Jackson 1, should be supported in Jackson 2 (this is where backwards compatibility plays a role).
In the remote case you have something that only can be deserialized with Jackson 1, you can still do a rolling upgrade in your project, the Jackson guys did an amazing job in this scenario, where they changed all packages name to com.fasterxml.jackson from the old org.codehaus.jackson, this means that both version can live in your classpath, allowing you to upgrade things based on priorities, or incrementally.
I have experience in the 3 scenarios I mentioned, since our projects used to use Jackson 1 and now we moved all of them to the latest and greatest.
Hope this helps,
Jose Luis
I couldn't find an answer to my question on the net (maybe I did not search well enough, since I am still a novice on this).
Could anyone tell me if Jackson and Gson implement the standard JSR 353: Java™ API for JSON Processing. I would like to write using standard code.
This link has the reply (apparently by the Jackson founder), and it essentially says that Jackson doesn't implement the JSR:
Reply by Tatu Saloranta on January 26, 2014 at 8:21pm
I am not a big fan of JSR-353 (I consider it a big fail) and unless something drastic happens, Jackson core will not implement JSR-353. There is no benefit from data-binding to use it; both because implementations do not bring anything to table (none are particularly fast), nor implement all that databind needs (base64 encoding, multi-format support capabilities) -- and worst of all ALL existing (de)serializers would need to be rewritten use new, less capable API. And baseline for Jackson would need to become Java 8. So I see no upside.
However, the reverse is possible; it is possible to have a JSR-353 implementation based on Jackson streaming package, and this has been done already:
https://github.com/pgelinas/jackson-javax-json.
Or, to make Jackson capable of reading/writing JSR-353 JSON object types, a simple datatype module is needed. I wrote one a while back:
https://github.com/FasterXML/jackson-datatype-jsr353
So if Java developers end up following "the standard" track, Jackson can play along.
Google didn't (couldn't?) vote on the JSR, and I couldn't find anything on Gson's roadmap either to suggest that they'd want to comply.
tl;dr
Use:
JSON-P
JSON-B
Update
The other two Answers are correct, but outdated. As they explain, Jackson does not directly implement any JSR.
However:
There is a project providing a datatype module to help make Jackson more compatible with JSR 353: jackson-datatype-jsr353.
JSR 353 is superseded by JSR 374: Java™ API for JSON Processing 1.1.
The JCP continued work on JSON support, for processing of JSON as well as binding yielding the pair of JSRs: 374 JSON-P & 367 JSON-B.
JSR 374 defines JSON processing (JSON-P).
See project page for JSON-P.
A reference implementation can be found in Glassfish, the reference implementation of Jakarta EE (formerly known as Java EE).
JSR 367 provides binding capabilities (JSON-B).
See the project page for JSON-B.
Yasson is the reference implementation.
So you may indeed now write in standard code using JSON libraries other than Jackson.
No, neither implements this API natively, nor has plans (that I know of) to implement it. As far as JCP standards go, this is DOA; it offers very little (dumbed-down streaming API, no data-binding at all), and there is very little incentive for anyone to implement it, except to add compatibility check-box for set of JSRs implemented.
There is a Jackson-based JSR-353 implementation available at https://github.com/pgelinas/jackson-javax-json/ however, if you really think it is good idea to base your code on this API.
The custom BeanSerializerFactory in http://kyrill007.livejournal.com/2577.html is the only custom solution I found to allow directly throwing persistent beans to JSON via Spring 3.0, and it works, it only serializes non initialized (lazy) attributes / collections (this allows me to use the entity Pojo as a DTO, as I initialize only what I want, and what is not initialized, doesn't get serialized to JSON)
But this worked well with Jackson 1.6, and I wanted to upgrade to Jackson 1.8 to solve the issue with Java Generics (hopefully) and now that custom solution is not compiling.
So my questions are
What is the recomended way to auto serialize Entities to JSON without the need of DTOs
Is there an official Hibernate Aware Jackson BeanSerializerFactory besides the above
I'm starting to fear that if it's that hard to find, maybe my practice is not the best one
What is the recommended way to do RESTful Ajax then with Spring 3.0 MVC and JSON?
The problems to solve are
Not serializing lazy attributes / collections automatially (as the custom code above does)
Supporting Java Generics and some kind of a client side object schema / validation
What works on get should work on save, and allow partial objects graphs to be returned safely
Is there Anything? do I have to manually write DTOs for every Entity?, this is so non productive
While SO has lots of experts, you might consider also asking on Jackson users list. Kirill (author of the blog entry) is responsive, and there are other experts there as well.
If I try to serialize a linq-to-sql entity, will it by default serialize only the primitive fields or will it try to access the relationship fields as well? If it tries to grab relationship fields, is there a way to override this?
Which serializer are you using?
The DataContractSerializer will
include loaded relationships but not
those that are not yet loaded / null.
The XmlSerializer tend to choke on relationships if they are bidirectional (i.e. entity A points to entity B which in turn points back).
The binaryformatter ... I never got that one to work properly with L2S entity objects having relationships to other entities. Long time since I tried though, so maybe I just did something wrong...
Another point to add to the accepted answer:
Relationships that are not collections will never be serialized by DataContractSerializer (whether they are loaded or not), because no DataMember attribute is generated for them from the .dbml file.
I found here an explanation by then-at-Microsoft Daniel Simmons:
The issue here is that prior to SP1 there was really no good way with DataContract serialization to handle graphs of objects that had cycles. As a result for LINQ to SQL the compromise decision was made to allow users to opt-in for uni-directional serialization and to only serialize collections not references. This mechanism doesn't work well for cases where you really want to serialize a reference (like your scenario above), but it at least gets you going for some common scenarios.
In SP1 new support was added to WCF which enables DataContract serialization to deal with cycles, but it is something you must opt-in to by changing some of your DataContract attributes and potentially also making changes to your collection and reference class implementations to properly handle the serializaiton and especially the deserialization behaviors of WCF. In the Entity Framework the changes were made to take advantage of these new features since it had not yet released its very first version, but Linq to SQL only had a small service-pack upgrade in sp1 and it was not modified to take advantage of this capability.
I have not experimented with this on L2S, but it might be possible to generate your own classes which work with L2S and have the right support for WCF serialization with cycles.
Danny