Custom object identities

106 views
Skip to first unread message

Rob

unread,
Nov 6, 2014, 4:04:56 AM11/6/14
to jackso...@googlegroups.com
I asked the same question also on Stackoverflow: http://stackoverflow.com/questions/26760299/custom-object-identities-in-json-serialisation

When serialising object graphs with circular dependencies to JSON you need to somehow cope with it to prevent the JSON from being infinitely large. Jackson provides functionality to track the identity of objects and uses references as soon as an object is to be serialised a second time, see for example here

Consider a list of the following classes is being serialised

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class FooBar
{
   
public String foo;
}



If the same object is present in the list multiple times, this results in the following serialised JSON string

[
   
{
   
"@id": 1,
   
"foo":"bar"
   
},
   
{
   
"@id": 2,
   
"foo":"baz"
   
},
   
1 //reference to the object with @id = 1
]


When you are in a strongely typed environment where you know the structure of the objects you want to have deserialised from this JSON, this is not a problem. If you don't know the structure, however, there is the problem that you have no idea which items are references and which are simple integers, right?

Now, a very simple solution would be to have the JSON look like this:

[
   
{
   
"@id": 1,
   
"foo":"bar"
   
},
   
{
   
"@id": 2,
   
"foo":"baz"
   
},
   
{
   
"@ref":1
   
}
]

This way you can simply go through your whole object graph and check for each object if it has a member `@ref`, if so you replace it with the corresponding object.

I want to generate JSON which looks like the second example. Has anyone done this already? If not, would the correct starting point be a custom ObjectIdGenerator or a custom Serializer?

Jeff Schnitzer

unread,
Nov 6, 2014, 3:29:59 PM11/6/14
to jackso...@googlegroups.com
Yes, almost exactly as you describe it:


With JavaScript, Ruby, Python implementations:


The JS, Ruby, and Python versions are complete. However, the jackson plugin only serializes to JSOG. I couldn't figure out how to implement deserialization, and it wasn't a pressing issue at the time.

Jeff

--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tatu Saloranta

unread,
Nov 7, 2014, 2:15:19 PM11/7/14
to jackso...@googlegroups.com
I remember this work. Did you end up writing an article on how this was done?

-+ Tatu +-

Jeff Schnitzer

unread,
Nov 20, 2014, 6:59:40 PM11/20/14
to jackso...@googlegroups.com
Somehow I missed the followup for this thread, sorry. Back in the day I wrote an announcement here:


This thread has great timing because I suddenly find myself needing to deserialize JSOG. Unfortunately I'm really struggling to figure out how this works. As redben pointed out, there's this comment:


However, my tests don't seem to execute that function (deserializeWithType). I'm having a hard time figuring out what code path would cause that function to execute - what triggers it?

Thanks,
Jeff

Tatu Saloranta

unread,
Nov 20, 2014, 10:21:30 PM11/20/14
to jackso...@googlegroups.com
On Thu, Nov 20, 2014 at 3:59 PM, Jeff Schnitzer <je...@infohazard.org> wrote:
Somehow I missed the followup for this thread, sorry. Back in the day I wrote an announcement here:


This thread has great timing because I suddenly find myself needing to deserialize JSOG. Unfortunately I'm really struggling to figure out how this works. As redben pointed out, there's this comment:


However, my tests don't seem to execute that function (deserializeWithType). I'm having a hard time figuring out what code path would cause that function to execute - what triggers it?

That is called by containing deserializer: for POJOs, via `SettableBeanProperty`. Container/Map/array deserializers call it directly, if a TypeDeserializer was found for the type.

I think that it'd make sense to create a simplified test for JSOG use case; since code path is twisty and crooked, I can try to untangle it -- I remember having gone through it back in the day, but at this point it's easier to follow a unit test.

-+ Tatu +-

Jeff Schnitzer

unread,
Nov 20, 2014, 11:39:05 PM11/20/14
to jackso...@googlegroups.com
Ok. Tomorrow I will try to create the simplest possible test case and submit it as a PR.

Thanks,
Jeff

Jeff Schnitzer

unread,
Nov 23, 2014, 3:48:43 PM11/23/14
to jackso...@googlegroups.com
Looks like you beat me to it - I just noticed JSOGDeserialize622Test.

Thanks,
Jeff
Reply all
Reply to author
Forward
0 new messages