Deserializing in place
JSON is merged into the instance you pass. Nested objects are updated where they are, collection elements are matched by ID.
Setup
Three collaborators
deserialize needs a Bean Validation validator, an EntityLoader for references, and an inject function that creates helpers. Create them once and reuse them.
scala
import com.anjunar.json.mapper.EntityLoader
import jakarta.validation.Validation
val validator = Validation.buildDefaultValidatorFactory().getValidator
val loader: EntityLoader = (id, clazz) => entityManager.find(clazz, id)
val inject = [T] => (clazz: Class[T]) => clazz.getDeclaredConstructor().newInstance()
Call
Parse, then merge
JsonParser turns text into the mapper's JSON nodes. deserialize writes every property present in the JSON into the target and returns it.
scala
import com.anjunar.json.mapper.JsonMapper
import com.anjunar.json.mapper.intermediate.JsonParser
import com.anjunar.scala.universe.TypeResolver
val target = new UserDto
target.address = new AddressDto
JsonMapper.deserialize(
JsonParser.parse("""{"name": "Updated User", "age": 35, "address": {"city": "Hamburg", "zipCode": "20095"}}"""),
target, TypeResolver.resolve(classOf[UserDto]), null, loader, inject, validator
)
println(target.name) // Updated User
println(target.address.city) // Hamburg
Semantics
What a merge means per kind of property
A property missing from the JSON stays as it is. A property set to null is cleared. Everything else depends on the type.
- value (String, Int, UUID, …)
- Replaced by the JSON value.
- object (DTO)
- An existing object is updated in place. Without one, an "id" is looked up through the EntityLoader; otherwise a new instance is created with the no-arg constructor.
- java.util.Collection
- Becomes exactly the elements in the JSON. Elements with an "id" matching an existing one are updated, not replaced; missing ones are removed.
- java.util.Map
- Cleared and filled with the JSON's entries.
- id
- Never written. Identity is not something a client may change.
Initialize collections
Collection and map properties must hold an instance before deserialization; the mapper fills them and never creates them. A null collection is an IllegalStateException.