Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow adding of external Object Id resolver #176

Closed
cowtowncoder opened this issue Feb 25, 2013 · 14 comments
Closed

Allow adding of external Object Id resolver #176

cowtowncoder opened this issue Feb 25, 2013 · 14 comments
Milestone

Comments

@cowtowncoder
Copy link
Member

(note: related to #138)

Currently it is assumed that all Object Id resolution is handled internally, using only information available from POJOs to serialize, or coming from JSON to deserialize.
This works acceptably when the default "serialize first instance seen, use ids for rest" handling, but not when trying to deserialize entries when using "always use id", since in latter case JSON itself just does not have actual things being referred.

This should be possible to handle by allowing use of external Object Id resolvers, which would be used if id is not resolvable using JSON content. This object could be called only in cases where it is known to be needed (when resolving references that have "alwaysUseId" marker).

@miguelcobain
Copy link

Hi!
I stumbled upon this problem. I'm using @JsonIdentityReference(alwaysAsId = true) in some references (collections and single object composition). Serialization works great, but when deserializing the following error comes up:

SEVERE: Servlet.service() for servlet [SpringApplication] in context with path [/workwise] threw exception [org.glassfish.jersey.server.ContainerException: com.fasterxml.jackson.databind.JsonMappingException: Could not resolve Object Id [3] (for [simple type, class eu.wiseworks.workwise.domain.enums.Type]) -- unresolved forward-reference? (through reference chain: eu.wiseworks.workwise.domain.WorkOrder["type_id"])] with root cause
java.lang.IllegalStateException: Could not resolve Object Id [3] (for [simple type, class eu.wiseworks.workwise.domain.enums.Type]) -- unresolved forward-reference?
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectId(BeanDeserializerBase.java:962)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:890)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:462)
    (...)

Right now is there any way to circumvent this?
I wouldn't mind to help the Deserialization with some code.
Thanks.

@cowtowncoder
Copy link
Member Author

Without having a way to reproduce the issue it is impossible to say what happens. But one possibility is, as exception states, there is unresolved forward reference (current JSON Object references something that is yet to come in stream). Jackson itself makes sure never to produce JSON it could not deserialize (in this regard), but some other packages may shuffle ordering of object properties.
Jackson will handle cases where Object Id of JSON Object is not the first JSON property, and reorder it; but this will not resolve all possible ordering issues.

Ideally forward references would be resolved, but the issue here is that of keeping track of property accessors (setter/field) of objects; and that would require significant rewrite of internals. I hope this will get done in future, but there is no active work for this (that is, nothing that is known to solve the issue).

Above is strictly assuming that the problem is due to reordering of JSON entries: if so, enforcing processing where ordering of JSON Object properties is strictly retained would avoid the issue.

@miguelcobain
Copy link

Could you illustrate with an example when the order of the fields in the JSON impossibilitate Jackson from Deserializing?

Thank you.

@cowtowncoder
Copy link
Member Author

How about I will try a definition. Any reference from property earlier in JSON input than the referred object is problematic, with one exception. The exception is that "object id" property of a POJO will always be reordered by Jackson (using buffering if necessary) to be seen as the first property. So this exception can resolve a subset of potential forward-references.

@miguelcobain
Copy link

Thank you.

One thing is confusing me, though.
I'm using alwaysAsId = true in an object property. That means that during serialization only the id of this object is sent from the server to the client. Always, not just after the first reference.

Similarly, when the client sends JSON to the server, it only references the id of the object as well.
It appears that in my case, this isn't a question of "referencing something that is still yet to come", but rather "referencing something that will not come". The object is referenced by Id. It is assumed that both the client and server know what object this Id refers to.

I'm not expecting Jackson to magically deserialize my entire object with only the id. But I would want it to create the object with only the Id assigned or to be able to provide a little helper for Jackson in these situations.

Is any of this possible? Basically the main question is: can Jackson deserialize an object with only its id (identity) and nothing else?

(Sorry for my persistence. 😄 )

@cowtowncoder
Copy link
Member Author

Ah yes, that does explain the issue.

Use of 'alwaysAsId' assumes that either:

  1. You do not deserialize with Jackson (or if you do, manage to make it not care about missing linkage), or
  2. You only use 'alwaysAsId' for some properties, and id still gets produced by different kind of reference (I don't even know how exactly you would do that, come to think of it)

So, no; if full object with id is not serialized, Jackson can not deduce ids automatically.

It should be possible to override object id handling on deserialization to figure out id->instance mapping from external sources; but this is not something that has been thought out, or fully designed. But existing end points used by standard functionality can be overridden and modified, and may allow doing that.
So it is neither impossible, nor do I know exactly how to do that.

And now that I read my original description again, yes, the idea with this issue was to investigate how to make this cleanly extensible, supportable. We are always open to ideas, suggestion, code patches!
(but, FWIW, no work has been done in this area)

@miguelcobain
Copy link

Ah, now makes sense. 😄

Thank you for the explanation. I've managed to get the same behavior (outputting only the Id on object relations instead of full object) by writing a custom serializer and deserializer, and then annotating the properties with @JsonSerialize(using=MySerializer.class).
I'm still having some doubts on this. I created this SO question: http://stackoverflow.com/questions/18528945/how-to-make-jackson-serializer-more-dry

Thank you!

@cowtowncoder
Copy link
Member Author

Ok good.

@jh3141
Copy link

jh3141 commented Jan 30, 2014

I'm currently in the planning stages of a project that would need to make use of this feature if it were to use jackson. I'm therefore wondering:

  1. Has any progress been made on this since you last commented?
  2. If not, do you have any suggestions on how I (as a new contributor with no experience working on jackson's code base) could go about adding it?

@cowtowncoder
Copy link
Member Author

@jh3141 I have not had time to look into this. Let me cc @pgelinas to see if he might be able to help here, since he has worked wonders with Object Id handling code (for 2.4).

@pgelinas
Copy link
Member

I can take a look. I'm about done with @JsonUnwrapped support in the xml module, this can be the next thing I tackle. I might even use this feature myself!

@cowtowncoder
Copy link
Member Author

@pgelinas great. This dropped from my radar; I suspect it could be easy to handle. And if need be I can work on that in a week or so -- right now I have bit of fire drill at work, so I have mostly just patched lowest hanging fruits for Jackson.

@pgelinas
Copy link
Member

pgelinas commented Feb 3, 2014

I've got a first version going, basically mimics what has been done for generator during serialization. API is very similar, I just need to clean some more and I'll send a PR your way.

@cowtowncoder
Copy link
Member Author

Implemented as per merged PR #401.

christophercurrie pushed a commit to christophercurrie/jackson-databind that referenced this issue Jul 19, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants