Guide for testing JSON serialization/deserialization with Spring Boot Test AutoConfigure.
Test slice pattern for isolated, fast JSON tests without full application context.
Key components: @JsonTest, @AutoConfigureJsonTesters, @AutoConfigureJson, JSON Tester beans (JacksonTester, GsonTester, JsonbTester, BasicJsonTester)
| Annotation | Loads Context | Auto-Configures Testers | Use Case |
|---|---|---|---|
@JsonTest | Test slice (JSON only) | Yes | Isolated JSON testing |
@AutoConfigureJsonTesters | No (add to existing test) | Yes | Add JSON testers to any test |
@AutoConfigureJson | No (add to existing test) | No | Add JSON library config only |
package org.springframework.boot.test.autoconfigure.json;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(JsonTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(JsonTypeExcludeFilter.class)
@AutoConfigureJsonTesters
@ImportAutoConfiguration
public @interface JsonTest {
/**
* Properties in "key=value" format added to test environment.
*/
String[] properties() default {};
/**
* If true, only @JacksonComponent and JacksonModule beans are included.
* Set to false to include all beans matched by includeFilters.
*/
boolean useDefaultFilters() default true;
/**
* Additional component filters to include beans.
*/
Filter[] includeFilters() default {};
/**
* Component filters to exclude beans.
*/
Filter[] excludeFilters() default {};
/**
* Auto-configuration classes to exclude.
*/
@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
Class<?>[] excludeAutoConfiguration() default {};
}Included: @JacksonComponent beans, Jackson modules, JSON library auto-config (Jackson/Gson/JSON-B), JSON tester beans
Excluded: Other auto-configurations (web, database, security), @Component/@Service/@Repository (unless included), @Configuration classes (unless included)
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@JsonTest
public class ProductJsonTests {
@Autowired
private JacksonTester<Product> json;
@Test
public void testSerialize() throws Exception {
Product product = new Product("laptop", 999.99, "Electronics");
assertThat(this.json.write(product))
.extractingJsonPathStringValue("@.name")
.isEqualTo("laptop");
assertThat(this.json.write(product))
.extractingJsonPathNumberValue("@.price")
.isEqualTo(999.99);
}
@Test
public void testDeserialize() throws Exception {
String content = """
{"name": "laptop", "price": 999.99, "category": "Electronics"}
""";
Product product = this.json.parse(content).getObject();
assertThat(product.getName()).isEqualTo("laptop");
}
@Test
public void testFile() throws Exception {
assertThat(this.json.write(new Product("laptop", 999.99, "Electronics")))
.isEqualToJson("expected-product.json");
Product product = this.json.read("product-sample.json").getObject();
assertThat(product.getName()).isNotNull();
}
}Note: JSON tester fields are automatically initialized by Spring's BeanPostProcessor when @Autowired is used on the field declaration.
Custom Jackson configuration:
@JsonTest(properties = {
"spring.jackson.serialization.indent-output=true",
"spring.jackson.serialization.write-dates-as-timestamps=false",
"spring.jackson.deserialization.fail-on-unknown-properties=false",
"spring.jackson.default-property-inclusion=non_null"
})
public class ConfiguredJsonTests {}Include components:
@JsonTest(includeFilters = {
@Filter(Component.class),
@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyJacksonModule.class)
})
public class JsonTestWithCustomComponents {}Exclude auto-configurations:
@JsonTest(excludeAutoConfiguration = {GsonAutoConfiguration.class, JsonbAutoConfiguration.class})
public class JacksonOnlyJsonTests {}Disable filters (not recommended):
@JsonTest(useDefaultFilters = false)
public class NoFilterJsonTests {}Test configuration:
@JsonTest
@Import(CustomJacksonConfiguration.class)
public class CustomConfigJsonTests {}Add JSON tester auto-configuration to non-JSON test slices.
package org.springframework.boot.test.autoconfigure.json;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigureJson
@ImportAutoConfiguration
@PropertyMapping("spring.test.jsontesters")
public @interface AutoConfigureJsonTesters {
/**
* Enable or disable JSON tester bean registration.
* Defaults to true.
*/
boolean enabled() default true;
}import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
@SpringBootTest
@AutoConfigureJsonTesters
public class IntegrationTestWithJson {
@Autowired
private JacksonTester<User> json;
@Autowired
private UserService userService; // Full application context available
@Test
public void testServiceOutputJson() throws Exception {
User user = userService.findUser("alice");
assertThat(this.json.write(user))
.extractingJsonPathStringValue("@.username")
.isEqualTo("alice");
}
}@WebMvcTest(UserController.class)
@AutoConfigureJsonTesters
public class ControllerWithJsonTests {
@Autowired
private MockMvc mockMvc;
@Autowired
private JacksonTester<User> json;
@Test
public void testControllerResponseAndJsonStructure() throws Exception {
// Test controller
MvcResult result = mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andReturn();
// Test JSON structure
String content = result.getResponse().getContentAsString();
User user = json.parse(content).getObject();
assertThat(user.getUsername()).isNotNull();
}
}Disable testers:
@SpringBootTest
@AutoConfigureJsonTesters(enabled = false)
public class NoJsonTestersTest {}Low-level annotation for JSON library auto-configuration without tester setup.
package org.springframework.boot.test.autoconfigure.json;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ImportAutoConfiguration
public @interface AutoConfigureJson {
}For JSON library configuration without testers:
@SpringBootTest
@AutoConfigureJson
public class ManualJsonTests {
@Autowired
private ObjectMapper objectMapper;
@Test
public void testWithObjectMapper() throws Exception {
User user = new User("alice");
String json = objectMapper.writeValueAsString(user);
assertThat(json).contains("\"username\":\"alice\"");
}
}Prefer @JsonTest or @AutoConfigureJsonTesters.
| Tester | Library Required | Maven Coordinates | Auto-Configured When |
|---|---|---|---|
| BasicJsonTester | None | N/A (Spring Boot built-in) | Always |
| JacksonTester | Jackson | org.springframework.boot:spring-boot-jackson | Jackson module on classpath |
| GsonTester | Gson | org.springframework.boot:spring-boot-gson | Gson module on classpath |
| JsonbTester | JSON-B | org.springframework.boot:spring-boot-jsonb | JSON-B module on classpath |
IMPORTANT: Spring Boot 4.0.0+ requires Spring Boot module dependencies (not raw library dependencies) for JSON testing.
<!-- Required for JacksonTester - Spring Boot Jackson module -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jackson</artifactId>
<scope>test</scope>
</dependency>
<!-- Required for JSON path assertions (.extractingJsonPathStringValue(), etc.) -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<!-- Required for JSON tester auto-configuration (@ConditionalOnJsonTesters) -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>Gradle:
testImplementation 'org.springframework.boot:spring-boot-jackson'
testImplementation 'com.jayway.jsonpath:json-path'
testImplementation 'org.assertj:assertj-core'Note: The spring-boot-jackson module includes Jackson 3.x with group ID tools.jackson.core. Do not add raw Jackson dependencies (com.fasterxml.jackson.core) as they may conflict with Spring Boot's Jackson 3.x integration.
<!-- For GsonTester support -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-gson</artifactId>
<scope>test</scope>
</dependency>Gradle:
testImplementation 'org.springframework.boot:spring-boot-gson'<!-- For JsonbTester support -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jsonb</artifactId>
<scope>test</scope>
</dependency>Gradle:
testImplementation 'org.springframework.boot:spring-boot-jsonb'Basic JSON tester that works with any JSON library. Provides assertion methods without serialization.
Defined in: org.springframework.boot.test.json (spring-boot-test module)
@JsonTest
public class BasicJsonTests {
@Autowired
private BasicJsonTester basicJson;
@Test
public void testJsonStructure() {
String json = "{\"name\":\"alice\",\"age\":30}";
assertThat(basicJson.from(json))
.hasJsonPathStringValue("@.name", "alice");
assertThat(basicJson.from(json))
.hasJsonPathNumberValue("@.age", 30);
assertThat(basicJson.from(json))
.extractingJsonPathStringValue("@.name")
.isEqualTo("alice");
}
@Test
public void testJsonFile() {
assertThat(basicJson.from("user.json"))
.hasJsonPathValue("@.username");
}
}Tester for Jackson (com.fasterxml.jackson) JSON processing.
Defined in: org.springframework.boot.test.json (spring-boot-test module)
@JsonTest
public class JacksonTests {
@Autowired
private JacksonTester<User> json;
@Test
public void testWrite() throws Exception {
User user = new User("alice", 30);
// Get JSON content
JsonContent<User> content = this.json.write(user);
// Assert using AssertJ
assertThat(content).extractingJsonPathStringValue("@.name")
.isEqualTo("alice");
assertThat(content).extractingJsonPathNumberValue("@.age")
.isEqualTo(30);
// Get raw JSON string
String jsonString = content.getJson();
// Compare to file
assertThat(content).isEqualToJson("expected-user.json");
// Check for absence
assertThat(content).doesNotHaveJsonPath("@.password");
}
@Test
public void testRead() throws Exception {
String json = "{\"name\":\"alice\",\"age\":30}";
// Parse JSON
ObjectContent<User> content = this.json.parse(json);
// Get parsed object
User user = content.getObject();
assertThat(user.getName()).isEqualTo("alice");
assertThat(user.getAge()).isEqualTo(30);
}
@Test
public void testReadFromFile() throws Exception {
// Read from classpath file
User user = this.json.read("user-sample.json").getObject();
assertThat(user).isNotNull();
}
@Test
public void testReadFromBytes() throws Exception {
byte[] jsonBytes = "{\"name\":\"alice\"}".getBytes();
User user = this.json.parse(jsonBytes).getObject();
assertThat(user.getName()).isEqualTo("alice");
}
}Tester for Gson (com.google.gson) JSON processing.
Defined in: org.springframework.boot.test.json (spring-boot-test module)
@JsonTest
public class GsonTests {
@Autowired(required = false)
private GsonTester<User> gsonJson;
@Test
public void testGson() throws Exception {
if (gsonJson == null) {
return; // Skip if Gson not available
}
User user = new User("alice", 30);
// Write JSON
JsonContent<User> content = this.gsonJson.write(user);
assertThat(content.getJson()).contains("\"name\":\"alice\"");
// Read JSON
String json = "{\"name\":\"alice\",\"age\":30}";
User parsed = this.gsonJson.parse(json).getObject();
assertThat(parsed.getName()).isEqualTo("alice");
}
}Tester for JSON-B (Jakarta JSON Binding) processing.
Defined in: org.springframework.boot.test.json (spring-boot-test module)
@JsonTest
public class JsonbTests {
@Autowired(required = false)
private JsonbTester<User> jsonbJson;
@Test
public void testJsonb() throws Exception {
if (jsonbJson == null) {
return; // Skip if JSON-B not available
}
User user = new User("alice", 30);
// Write JSON
String json = this.jsonbJson.write(user).getJson();
assertThat(json).contains("\"name\":\"alice\"");
// Read JSON
String content = "{\"name\":\"alice\",\"age\":30}";
User parsed = this.jsonbJson.parse(content).getObject();
assertThat(parsed.getName()).isEqualTo("alice");
}
}All JSON testers return AssertJ-compatible assertion objects with these methods:
JsonContent<T> content = json.write(object);
// Extract and assert JSON path values
assertThat(content).extractingJsonPathStringValue("@.name").isEqualTo("alice");
assertThat(content).extractingJsonPathNumberValue("@.age").isEqualTo(30);
assertThat(content).extractingJsonPathBooleanValue("@.active").isTrue();
assertThat(content).extractingJsonPathArrayValue("@.tags").hasSize(3);
assertThat(content).extractingJsonPathMapValue("@.address").containsKey("city");
// Check for JSON path presence
assertThat(content).hasJsonPathValue("@.name");
assertThat(content).hasJsonPathStringValue("@.name", "alice");
assertThat(content).hasJsonPathNumberValue("@.age", 30);
// Check for JSON path absence
assertThat(content).doesNotHaveJsonPath("@.password");
assertThat(content).doesNotHaveJsonPathValue("@.secretField");
// Compare to expected JSON
assertThat(content).isEqualToJson("{\"name\":\"alice\"}");
assertThat(content).isEqualToJson("expected.json"); // File comparison
// Strict equality (order matters)
assertThat(content).isStrictlyEqualToJson("{\"name\":\"alice\",\"age\":30}");
// Check if JSON is subset of expected
assertThat(content).isEqualToJson("{\"name\":\"alice\"}", JSONCompareMode.LENIENT);
// Get raw JSON string
String jsonString = content.getJson();ObjectContent<User> content = json.parse(jsonString);
// Get parsed object
User user = content.getObject();
// Use standard AssertJ assertions on object
assertThat(user).isNotNull();
assertThat(user.getName()).isEqualTo("alice");package org.springframework.boot.test.autoconfigure.json;
@AutoConfiguration
@ConditionalOnJsonTesters
public final class JsonTestersAutoConfiguration {
// Registers bean post-processors and factory beans
// Package-private bean factory methods
}Registered when:
@ConditionalOnJsonTesters conditions metspring.test.jsontesters.enabled is true (default)Registers:
package org.springframework.boot.test.autoconfigure.json;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnBooleanProperty("spring.test.jsontesters.enabled")
@ConditionalOnClass(name = "org.assertj.core.api.Assert")
public @interface ConditionalOnJsonTesters {
}Conditions:
spring.test.jsontesters.enabled is true (defaults to true via metadata)org.assertj.core.api.Assert is on classpathpackage org.springframework.boot.test.autoconfigure.json;
import org.springframework.beans.factory.FactoryBean;
import org.jspecify.annotations.Nullable;
public final class JsonTesterFactoryBean<T, M> implements FactoryBean<T> {
public JsonTesterFactoryBean(Class<?> objectType, @Nullable M marshaller);
@Override
public T getObject() throws Exception;
@Override
public Class<?> getObjectType();
@Override
public boolean isSingleton();
}Type parameters:
Usage: Internal factory bean for creating JSON tester instances. Not used directly in tests.
package org.springframework.boot.test.autoconfigure.json;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.boot.test.json.AbstractJsonMarshalTester;
import org.jspecify.annotations.Nullable;
public abstract class JsonMarshalTesterRuntimeHints implements RuntimeHintsRegistrar {
/**
* Create a new JsonMarshalTesterRuntimeHints instance for the given tester class.
* @param tester the JSON marshal tester class
*/
protected JsonMarshalTesterRuntimeHints(
Class<? extends AbstractJsonMarshalTester> tester) {
// Stores tester class for hint registration
}
/**
* Register runtime hints for GraalVM native image.
* Registers reflection hints for the tester class declared constructors and the
* initialize(Class<?>, ResolvableType) method to enable JSON tester functionality
* in native images.
* @param hints the runtime hints instance
* @param classLoader the classloader, or null
*/
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader);
}Purpose: Registers GraalVM native image runtime hints for JSON testers to ensure reflection works in native images.
Implementations:
Type: boolean Default: true
Enable or disable JSON tester auto-configuration.
spring:
test:
jsontesters:
enabled: falseOr in test annotation:
@JsonTest(properties = "spring.test.jsontesters.enabled=false")
public class ManualJsonTests {
// JSON testers will not be auto-configured
}Configure Jackson behavior in tests:
spring:
jackson:
serialization:
indent-output: true
write-dates-as-timestamps: false
fail-on-empty-beans: false
deserialization:
fail-on-unknown-properties: false
default-property-inclusion: non_null
date-format: yyyy-MM-dd'T'HH:mm:ss.SSSZOr in @JsonTest:
@JsonTest(properties = {
"spring.jackson.serialization.indent-output=true",
"spring.jackson.deserialization.fail-on-unknown-properties=false"
})Symptom: JacksonTester field is null or NullPointerException when using it
Cause: JSON tester fields are not Spring beans - they are initialized by a BeanPostProcessor
Solutions:
Use @Autowired - JSON tester fields must be autowired to be initialized:
@JsonTest
public class MyJsonTests {
@Autowired
private JacksonTester<MyType> json; // Correct - @Autowired required
}Add ALL required dependencies - all three are mandatory:
<!-- Required for JacksonTester - Spring Boot Jackson module -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jackson</artifactId>
<scope>test</scope>
</dependency>
<!-- Required for JSON path assertions -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<!-- Required for auto-configuration -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>Verify @JsonTest or @AutoConfigureJsonTesters present:
@JsonTest // Required
public class MyJsonTests {}Verify property not disabled:
@JsonTest(properties = "spring.test.jsontesters.enabled=true")Symptom: NoClassDefFoundError for json-path classes when using JSON testers
Cause: Missing json-path dependency (required but not documented in older guides)
Solution:
Add the json-path dependency:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>Note: JSON path is required for JSON tester assertion methods like .extractingJsonPathStringValue().
Symptom: Gson or JSON-B tester field is null
Cause: Library not on classpath (these are optional)
Solution:
Check for null before using optional testers:
@JsonTest
public class MultiLibraryTests {
@Autowired
private JacksonTester<User> jacksonJson; // Always available
@Autowired(required = false)
private GsonTester<User> gsonJson; // May be null
@Test
public void testGson() {
if (gsonJson == null) {
// Gson not available, skip test
return;
}
// Use gsonJson
}
}Symptom: Assertions fail with unexpected JSON
Solutions:
System.out.println("Actual: " + content.getJson())assertThat(content).isEqualToJson(expected, JSONCompareMode.LENIENT)@JsonTest(properties = "spring.jackson.default-property-inclusion=non_null")Symptom: Custom module/serializer not applied
Solutions:
@JacksonComponent public class CustomModule extends SimpleModule {}@JsonTest(includeFilters = @Filter(type = ASSIGNABLE_TYPE, classes = CustomModule.class))@Bean in @TestConfigurationSymptom: Different JSON output across libraries
Solutions:
Configure consistently:
// Jackson: exclude nulls
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {}
// Gson: configure via GsonBuilder bean
@TestConfiguration
static class GsonConfig {
@Bean
public Gson gson() {
return new GsonBuilder()
.serializeNulls(false)
.create();
}
}Use library-specific annotations:
@JsonProperty("userName") // Jackson
@SerializedName("userName") // Gson
private String name;Test each library separately:
@JsonTest
public class JacksonOnlyTests {
@Autowired
private JacksonTester<User> json;
// Test Jackson behavior
}Test custom Jackson serializers:
@JacksonComponent
public class CustomSerializer extends JsonSerializer<MyType> {
@Override
public void serialize(MyType value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
gen.writeStartObject();
gen.writeStringField("customField", value.process());
gen.writeEndObject();
}
}
@JsonTest
public class CustomSerializerTests {
@Autowired
private JacksonTester<MyType> json;
@Test
public void testCustomSerializer() throws Exception {
MyType obj = new MyType("input");
assertThat(this.json.write(obj))
.extractingJsonPathStringValue("@.customField")
.isEqualTo("processed-input");
}
}Test date serialization formats:
@JsonTest(properties = "spring.jackson.date-format=yyyy-MM-dd")
public class DateFormatTests {
@Autowired
private JacksonTester<Event> json;
@Test
public void testDateFormat() throws Exception {
Event event = new Event("meeting", LocalDate.of(2025, 1, 15));
assertThat(this.json.write(event))
.extractingJsonPathStringValue("@.date")
.isEqualTo("2025-01-15");
}
}Test Jackson polymorphic type handling:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {}
@JsonTest
public class PolymorphicTests {
@Autowired
private JacksonTester<Animal> json;
@Test
public void testPolymorphicSerialization() throws Exception {
Animal dog = new Dog("Buddy");
assertThat(this.json.write(dog))
.extractingJsonPathStringValue("@.type")
.isEqualTo("dog");
assertThat(this.json.write(dog))
.extractingJsonPathStringValue("@.name")
.isEqualTo("Buddy");
}
@Test
public void testPolymorphicDeserialization() throws Exception {
String json = "{\"type\":\"cat\",\"name\":\"Whiskers\"}";
Animal animal = this.json.parse(json).getObject();
assertThat(animal).isInstanceOf(Cat.class);
assertThat(((Cat) animal).getName()).isEqualTo("Whiskers");
}
}Use multiple testers in one test:
@JsonTest
public class MultiTypeTests {
@Autowired
private JacksonTester<User> userJson;
@Autowired
private JacksonTester<Product> productJson;
@Autowired
private JacksonTester<Order> orderJson;
@Test
public void testMultipleTypes() throws Exception {
User user = new User("alice");
Product product = new Product("laptop");
Order order = new Order(user, product);
// Test each type independently
assertThat(userJson.write(user)).hasJsonPathValue("@.name");
assertThat(productJson.write(product)).hasJsonPathValue("@.name");
assertThat(orderJson.write(order)).hasJsonPathValue("@.user");
}
}Test Jackson @JsonView serialization:
public class Views {
public static class Public {}
public static class Internal extends Public {}
}
public class User {
@JsonView(Views.Public.class)
private String name;
@JsonView(Views.Internal.class)
private String email;
}
@JsonTest
public class JsonViewTests {
@Autowired
private ObjectMapper objectMapper;
@Test
public void testPublicView() throws Exception {
User user = new User("alice", "alice@example.com");
String json = objectMapper
.writerWithView(Views.Public.class)
.writeValueAsString(user);
assertThat(json).contains("\"name\":\"alice\"");
assertThat(json).doesNotContain("\"email\"");
}
@Test
public void testInternalView() throws Exception {
User user = new User("alice", "alice@example.com");
String json = objectMapper
.writerWithView(Views.Internal.class)
.writeValueAsString(user);
assertThat(json).contains("\"name\":\"alice\"");
assertThat(json).contains("\"email\":\"alice@example.com\"");
}
}@JsonTest
public class NullHandlingTests {
@Autowired
private JacksonTester<User> json;
@Test
public void testNullField() throws Exception {
User user = new User("alice", null); // null email
// With default config, null fields included
assertThat(this.json.write(user).getJson())
.contains("\"email\":null");
}
@Test
public void testExcludeNulls() throws Exception {
// Configure to exclude nulls
User user = new User("alice", null);
// Need custom ObjectMapper or @JsonInclude annotation
assertThat(this.json.write(user).getJson())
.doesNotContain("\"email\"");
}
@Test
public void testDeserializeNull() throws Exception {
String json = "{\"name\":\"alice\",\"email\":null}";
User user = this.json.parse(json).getObject();
assertThat(user.getName()).isEqualTo("alice");
assertThat(user.getEmail()).isNull();
}
}@Test
public void testEmptyArray() throws Exception {
UserList users = new UserList(Collections.emptyList());
assertThat(this.json.write(users))
.extractingJsonPathArrayValue("@.users")
.isEmpty();
}
@Test
public void testEmptyObject() throws Exception {
EmptyObject obj = new EmptyObject();
// May fail with default Jackson config
// Add property: spring.jackson.serialization.fail-on-empty-beans=false
String json = this.json.write(obj).getJson();
assertThat(json).isEqualTo("{}");
}@Test
public void testSpecialCharacters() throws Exception {
User user = new User("alice \"the great\"", "test@example.com");
assertThat(this.json.write(user))
.extractingJsonPathStringValue("@.name")
.isEqualTo("alice \"the great\""); // Quotes properly escaped
}
@Test
public void testUnicodeCharacters() throws Exception {
User user = new User("José García", "josé@example.com");
String json = this.json.write(user).getJson();
assertThat(json).contains("José García"); // Unicode preserved
}@Test
public void testLargeNumbers() throws Exception {
Product product = new Product("item", 9999999999999.99);
assertThat(this.json.write(product))
.extractingJsonPathNumberValue("@.price")
.isEqualTo(9999999999999.99);
}
@Test
public void testBigDecimal() throws Exception {
// Use BigDecimal for precise decimal values
Payment payment = new Payment(new BigDecimal("123.456789"));
String json = this.json.write(payment).getJson();
assertThat(json).contains("123.456789"); // No precision loss
}JacksonTester<T>: org.springframework.boot.test.json.JacksonTesterGsonTester<T>: org.springframework.boot.test.json.GsonTesterJsonbTester<T>: org.springframework.boot.test.json.JsonbTesterBasicJsonTester: org.springframework.boot.test.json.BasicJsonTesterAbstractJsonMarshalTester: org.springframework.boot.test.json.AbstractJsonMarshalTesterJsonContent<T>: org.springframework.boot.test.json.JsonContentObjectContent<T>: org.springframework.boot.test.json.ObjectContentFactoryBean<T>: org.springframework.beans.factory.FactoryBeanRuntimeHintsRegistrar: org.springframework.aot.hint.RuntimeHintsRegistrarRuntimeHints: org.springframework.aot.hint.RuntimeHintsAssert: org.assertj.core.api.Assert (required for JSON tester auto-configuration)ObjectMapper: com.fasterxml.jackson.databind.ObjectMapperModule: com.fasterxml.jackson.databind.ModuleJsonSerializer: com.fasterxml.jackson.databind.JsonSerializerJsonDeserializer: com.fasterxml.jackson.databind.JsonDeserializerGson: com.google.gson.GsonGsonBuilder: com.google.gson.GsonBuilderJsonb: jakarta.json.bind.JsonbJsonbBuilder: jakarta.json.bind.JsonbBuilder