JSON

Spring Boot provides integration with three JSON mapping libraries:

  • Gson

  • Jackson

  • JSON-B

Jackson is the preferred and default library.

Jackson

Auto-configuration for Jackson is provided and Jackson is part of spring-boot-starter-json. When Jackson is on the classpath an ObjectMapper bean is automatically configured. Several configuration properties are provided for customizing the configuration of the ObjectMapper.

Custom Serializers and Deserializers

If you use Jackson to serialize and deserialize JSON data, you might want to write your own JsonSerializer and JsonDeserializer classes. Custom serializers are usually registered with Jackson through a module, but Spring Boot provides an alternative @JsonComponent annotation that makes it easier to directly register Spring Beans.

You can use the @JsonComponent annotation directly on JsonSerializer, JsonDeserializer or KeyDeserializer implementations. You can also use it on classes that contain serializers/deserializers as inner classes, as shown in the following example:

  • Java

  • Kotlin

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import org.springframework.boot.jackson.JsonComponent;

@JsonComponent
public class MyJsonComponent {

	public static class Serializer extends JsonSerializer<MyObject> {

		@Override
		public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
			jgen.writeStartObject();
			jgen.writeStringField("name", value.getName());
			jgen.writeNumberField("age", value.getAge());
			jgen.writeEndObject();
		}

	}

	public static class Deserializer extends JsonDeserializer<MyObject> {

		@Override
		public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
			ObjectCodec codec = jsonParser.getCodec();
			JsonNode tree = codec.readTree(jsonParser);
			String name = tree.get("name").textValue();
			int age = tree.get("age").intValue();
			return new MyObject(name, age);
		}

	}

}
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import org.springframework.boot.jackson.JsonComponent
import java.io.IOException

@JsonComponent
class MyJsonComponent {

	class Serializer : JsonSerializer<MyObject>() {
		@Throws(IOException::class)
		override fun serialize(value: MyObject, jgen: JsonGenerator, serializers: SerializerProvider) {
			jgen.writeStartObject()
			jgen.writeStringField("name", value.name)
			jgen.writeNumberField("age", value.age)
			jgen.writeEndObject()
		}
	}

	class Deserializer : JsonDeserializer<MyObject>() {
		@Throws(IOException::class, JsonProcessingException::class)
		override fun deserialize(jsonParser: JsonParser, ctxt: DeserializationContext): MyObject {
			val codec = jsonParser.codec
			val tree = codec.readTree<JsonNode>(jsonParser)
			val name = tree["name"].textValue()
			val age = tree["age"].intValue()
			return MyObject(name, age)
		}
	}

}

All @JsonComponent beans in the ApplicationContext are automatically registered with Jackson. Because @JsonComponent is meta-annotated with @Component, the usual component-scanning rules apply.

Spring Boot also provides JsonObjectSerializer and JsonObjectDeserializer base classes that provide useful alternatives to the standard Jackson versions when serializing objects. See JsonObjectSerializer and JsonObjectDeserializer in the Javadoc for details.

The example above can be rewritten to use JsonObjectSerializer/JsonObjectDeserializer as follows:

  • Java

  • Kotlin

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;

import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.jackson.JsonObjectDeserializer;
import org.springframework.boot.jackson.JsonObjectSerializer;

@JsonComponent
public class MyJsonComponent {

	public static class Serializer extends JsonObjectSerializer<MyObject> {

		@Override
		protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
				throws IOException {
			jgen.writeStringField("name", value.getName());
			jgen.writeNumberField("age", value.getAge());
		}

	}

	public static class Deserializer extends JsonObjectDeserializer<MyObject> {

		@Override
		protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
				JsonNode tree) throws IOException {
			String name = nullSafeValue(tree.get("name"), String.class);
			int age = nullSafeValue(tree.get("age"), Integer.class);
			return new MyObject(name, age);
		}

	}

}
/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.docs.features.json.jackson.customserializersanddeserializers.`object`

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.ObjectCodec
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.SerializerProvider
import org.springframework.boot.jackson.JsonComponent
import org.springframework.boot.jackson.JsonObjectDeserializer
import org.springframework.boot.jackson.JsonObjectSerializer
import java.io.IOException

@JsonComponent
class MyJsonComponent {

	class Serializer : JsonObjectSerializer<MyObject>() {
		@Throws(IOException::class)
		override fun serializeObject(value: MyObject, jgen: JsonGenerator, provider: SerializerProvider) {
			jgen.writeStringField("name", value.name)
			jgen.writeNumberField("age", value.age)
		}
	}

	class Deserializer : JsonObjectDeserializer<MyObject>() {
		@Throws(IOException::class)
		override fun deserializeObject(jsonParser: JsonParser, context: DeserializationContext,
				codec: ObjectCodec, tree: JsonNode): MyObject {
			val name = nullSafeValue(tree["name"], String::class.java)
			val age = nullSafeValue(tree["age"], Int::class.java)
			return MyObject(name, age)
		}
	}

}

Mixins

Jackson has support for mixins that can be used to mix additional annotations into those already declared on a target class. Spring Boot’s Jackson auto-configuration will scan your application’s packages for classes annotated with @JsonMixin and register them with the auto-configured ObjectMapper. The registration is performed by Spring Boot’s JsonMixinModule.

Gson

Auto-configuration for Gson is provided. When Gson is on the classpath a Gson bean is automatically configured. Several spring.gson.* configuration properties are provided for customizing the configuration. To take more control, one or more GsonBuilderCustomizer beans can be used.

JSON-B

Auto-configuration for JSON-B is provided. When the JSON-B API and an implementation are on the classpath a Jsonb bean will be automatically configured. The preferred JSON-B implementation is Eclipse Yasson for which dependency management is provided.