All frameworks
ANJUNAR / OPEN SOURCE

JSON Mapper

JSON mapping for existing object graphs and domain models.

01

The idea

A Scala 3 library that serializes and deserializes object graphs, including updates to existing instances. It supports nested graphs, structured binding, converters, and aggregated validation errors.

02

What it does.

01

In-place updates

Merge JSON into an existing domain object instead of replacing the whole graph.

02

Nested graphs

Map relationships, collections, and common domain value types.

03

Validation

Collect structured errors while binding incoming data.

03

Installation

Add to your project
libraryDependencies += "com.anjunar" %% "json-mapper" % "1.1.3"

Package: com.anjunar:json-mapper

04

Start building.

Add json-mapper and deserialize JSON into a new type or an existing object graph.

A nested domain object

JSON fields map onto the annotated DTO and its nested address.

Source code
import com.anjunar.json.mapper.provider.DTO
import jakarta.json.bind.annotation.JsonbProperty
import scala.annotation.meta.field

class AddressDto extends DTO {
  @(JsonbProperty @field) var city: String = null
}

class UserDto extends DTO {
  @(JsonbProperty @field) var name: String = null
  @(JsonbProperty @field) var address: AddressDto = null
}

Merge JSON into an existing instance

The mapper updates the existing graph and validates the result; the target instance keeps its identity.

Source code
import com.anjunar.json.mapper.{EntityLoader, JsonMapper}
import com.anjunar.json.mapper.intermediate.JsonParser
import com.anjunar.scala.universe.TypeResolver
import jakarta.validation.Validation
import java.util.UUID

val user = new UserDto
user.address = new AddressDto
val validator = Validation.buildDefaultValidatorFactory().getValidator
val loader = new EntityLoader {
  override def load(id: UUID, clazz: Class[?]): Any = null
}

val updated = JsonMapper.deserialize(
  JsonParser.parse("{\"name\":\"Ada\",\"address\":{\"city\":\"Berlin\"}}"),
  user,
  TypeResolver.resolve(classOf[UserDto]),
  null, // optional EntityGraph
  loader,
  [T] => (_: Class[T]) => null.asInstanceOf[T],
  validator
).asInstanceOf[UserDto]

assert(updated eq user)
assert(user.address.city == "Berlin")
05

By design.

Mapping into existing instances helps preserve identity and domain relationships during partial updates.

Your next step

Make it part of your stack.

Built carefully with Scala JS UI.Imprint