Describe the bug
I'm trying to use @JsonManagedReference
and @JsonBackReference
annotations to deserialize JSON representing a bi-directional relationship. This works well when using a default ObjectMapper()
with no extra configuration but the annotations seem to be ignored when using Spring Boot's configuration. I didn't find any settings regarding this behaviour so I don't think it can be explicitly enabled, thus possibly being a bug.
Version information 2.14.1
To Reproduce I built a small example meant to reproduce the issue (Kotlin):
@Entity
class User(
@Id
@GeneratedValue
var id: Long = 0,
var name: String? = null,
@JsonManagedReference
@OneToMany
var userItems: MutableList<Item> = mutableListOf()
)
@Entity
class Item(
@Id
@GeneratedValue
val id: Long = 0,
var itemName: String? = null,
@JsonBackReference
@ManyToOne
var owner: User? = null
)
@SpringBootTest
class ApplicationTests @Autowired constructor(private val objectMapper: ObjectMapper) {
@Test
fun customConfiguration() {
val userJson = """
{
"name": "John",
"userItems": [
{
"itemName": "book"
}
]
}
""".trimIndent()
val user = objectMapper.readValue(userJson, User::class.java)
assert(user.userItems[0].owner != null)
}
@Test
fun noConfiguration() {
val userJson = """
{
"name": "John",
"userItems": [
{
"itemName": "book"
}
]
}
""".trimIndent()
val user = ObjectMapper().readValue(userJson, User::class.java)
assert(user.userItems[0].owner != null)
}
}
The first test uses Spring's objectMapper (a different configuration from vanilla) and fails. The second test uses a default ObjectMapper and succeeds.
Expected behavior
I expected the items annotated with @JsonBackReference
to have correct references to the ones annotated with @JsonManagedReference
. In the example, I expect the item to have a correct reference to the user.
Additional context
I explored a bit through BeanDeserializer
's source code and found that deserializeAndSet()
is called when using the vanilla configuration (second test). However, when using deserializeFromObject()
(first case) the set()
function is never called, causing the reference to not be linked.
Is there some configuration I can override/remove or is this a bug that should be fixed?
Comment From: yawkat
can you make an example without spring? if not i think you should report this to the spring folks first, it's kind of hard to reason about why this happens if there is another framework involved
Comment From: BrunoRosendo
After some time debugging, I found the culprit was KotlinModule(). The problem is probably from that module and I found an issue for it: https://github.com/FasterXML/jackson-module-kotlin/issues/294
Anyway, here's the example without any Spring involved, if anybody is interested:
class User(
var id: Long = 0,
var name: String? = null,
@JsonManagedReference
var userItems: MutableList<Item> = mutableListOf()
)
class Item(
val id: Long = 0,
var itemName: String? = null,
@JsonBackReference
var owner: User? = null
)
class ApplicationTests {
@Test
fun customConfiguration() {
val objectMapper = ObjectMapper()
.registerModule(KotlinModule())
val userJson = """
{
"id": 0,
"name": "John",
"userItems": [
{
"id": 1,
"itemName": "book"
}
]
}
""".trimIndent()
val user = objectMapper.readValue(userJson, User::class.java)
assert(user.userItems[0].owner != null)
}
@Test
fun noConfiguration() {
val userJson = """
{
"id": 0,
"name": "John",
"userItems": [
{
"id": 1,
"itemName": "book"
}
]
}
""".trimIndent()
val user = ObjectMapper().readValue(userJson, User::class.java)
assert(user.userItems[0].owner != null)
}
}