JsonIdentityInfo and serializing ObjectId references - expected a field name

609 views
Skip to first unread message

Jeff Quandt

unread,
Jul 13, 2016, 4:30:23 PM7/13/16
to jackson-user
I'm using Jackson 2.8.0 to serialize some JPA Entities over a REST API with Spring Data REST. I'm having a problem with serializing an Array of Entities that contain references to the same child object. All objects are using JsonIdentityInfo as below, where the key property is a Long @Id field.

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "key", scope = MyClass.class)

I believe the expected JSON should look like the below. The relevant object is supportEmailAddress.

"companies" : [ {
 
"key" : 1,
 
"name" : "company1",
  "supportEmailAddress" : {
   
"key" : 1,
   
"emailAddrType" : "support",
   
"emailAddress" : "em...@support.com"
 
}

 
"aliases" : [ ],
 
"contacts" : [ ],
 
"owner" : {
   
"key" : 1,
   
"name" : "owner 1",
   
"contacts" : [ ],
   
"_links" : {
     
"company" : {
       
"href" : "http://localhost:8080/company/1"
     
}
   
}
 
}
}, {
 
"key" : 2,
 
"name" : "company2",
 
"supportEmailAddress" : {[1]}
 
"aliases" : [ ],
 
"contacts" : [ ],
 
"owner" : {
   
"key" : 2,
   
"name" : "owner 2",
   
"contacts" : [ ],
   
"_links" : {
     
"company" : {
       
"href" : "http://localhost:8080/company/2"
     
}
   
}
 
}

The first time the child object is referenced, it serializes correctly. The second time, it fails with the stack trace below.

<...>
Caused by: com.fasterxml.jackson.core.JsonGenerationException: Can not write a number, expecting field name
at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1676)
at com.fasterxml.jackson.core.json.UTF8JsonGenerator._verifyValueWrite(UTF8JsonGenerator.java:925)
at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeNumber(UTF8JsonGenerator.java:787)
at com.fasterxml.jackson.databind.ser.std.NumberSerializers$LongSerializer.serialize(NumberSerializers.java:188)
at com.fasterxml.jackson.databind.ser.impl.WritableObjectId.writeAsId(WritableObjectId.java:35)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase._serializeWithObjectId(BeanSerializerBase.java:584)
at com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer.serialize(UnwrappingBeanSerializer.java:114)
at com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter.serializeAsField(UnwrappingBeanPropertyWriter.java:127)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
at com.fasterxml.jackson.databind.SerializerProvider.defaultSerializeValue(SerializerProvider.java:985)
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer.serialize(PersistentEntityJackson2Module.java:193)
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer.serialize(PersistentEntityJackson2Module.java:140)
at com.fasterxml.jackson.databind.SerializerProvider.defaultSerializeValue(SerializerProvider.java:985)
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$NestedEntitySerializer.serialize(PersistentEntityJackson2Module.java:356)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)x
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase._serializeWithObjectId(BeanSerializerBase.java:600)
at com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer.serialize(UnwrappingBeanSerializer.java:114)
at com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter.serializeAsField(UnwrappingBeanPropertyWriter.java:127)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
at com.fasterxml.jackson.databind.SerializerProvider.defaultSerializeValue(SerializerProvider.java:985)
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer.serialize(PersistentEntityJackson2Module.java:193)
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer.serialize(PersistentEntityJackson2Module.java:140)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:616)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:519)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:31)
at org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer.serialize(Jackson2HalModule.java:340)
at org.springframework.hateoas.hal.Jackson2HalModule$HalResourcesSerializer.serialize(Jackson2HalModule.java:302)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1428)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:930)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:269)
... 57 more

If I remove the JsonIdentityInfo, I get the results back correctly. However, there are no Object references, and the full child object is serialized every time it is referenced. I'm concerned that this "fix" is not effective, because I originally added the JsonIdentityInfo annotations to get around some recursive relationships (ORM bi-directional stuff). If I have to remove them every time I might refer to the same instance in a result set, what is the point of the JsonIdentityInfo annotation in the first place? 

I'm sure I'm just applying something incorrectly, but I'm not able to find documentation on what I may be missing. Do I need a custom serializer to make use of this feature?

Tatu Saloranta

unread,
Jul 13, 2016, 4:40:44 PM7/13/16
to jackso...@googlegroups.com
This definitely sounds like a bug in Jackson; exception itself indicates that the state Jackson databind thinks it is in (wrt what is to be written) differs from what low-level JSON generator thinks.

If possible, could you file a bug at

https://github.com/FasterXML/jackson-databind/issues

but ideally with a (as simplified as possible) reproduction? Once we can reproduce the problem it should hopefully be easy to fix.

-+ Tatu +-


--
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.

Jeff Quandt

unread,
Jul 14, 2016, 4:48:15 PM7/14/16
to jackson-user
I created an issue for this item. 
Reply all
Reply to author
Forward
0 new messages