diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/JsonTestIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/JsonTestIntegrationTests.java index 205ef537c0..29b1563d28 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/JsonTestIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/JsonTestIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -16,6 +16,9 @@ package org.springframework.boot.test.autoconfigure.json; +import java.util.Date; +import java.util.UUID; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -75,7 +78,7 @@ class JsonTestIntegrationTests { @Test void jacksonCustom() throws Exception { - ExampleCustomObject object = new ExampleCustomObject("spring"); + ExampleCustomObject object = new ExampleCustomObject("spring", new Date(), UUID.randomUUID()); assertThat(this.jacksonCustomJson.write(object)).isEqualToJson("example.json"); } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleCustomObject.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleCustomObject.java index af2f31c1aa..17a0c0691e 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleCustomObject.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleCustomObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -16,35 +16,17 @@ package org.springframework.boot.test.autoconfigure.json.app; +import java.util.Date; +import java.util.UUID; + /** * Example object to read/write as JSON through {@link ExampleJsonComponent}. * * @author Phillip Webb + * @param value the value + * @param date a date + * @param uuid a uuid */ -public class ExampleCustomObject { - - private final String value; - - public ExampleCustomObject(String value) { - this.value = value; - } - - @Override - public boolean equals(Object obj) { - if (obj != null && obj.getClass() == getClass()) { - return this.value.equals(((ExampleCustomObject) obj).value); - } - return false; - } - - @Override - public int hashCode() { - return this.value.hashCode(); - } - - @Override - public String toString() { - return this.value; - } +public record ExampleCustomObject(String value, Date date, UUID uuid) { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonComponent.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonComponent.java index 803707687a..3cb4698f56 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonComponent.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2024 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. @@ -17,6 +17,8 @@ package org.springframework.boot.test.autoconfigure.json.app; import java.io.IOException; +import java.util.Date; +import java.util.UUID; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -44,7 +46,9 @@ public class ExampleJsonComponent { @Override protected void serializeObject(ExampleCustomObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeStringField("value", value.toString()); + jgen.writeStringField("value", value.value()); + jgen.writeNumberField("date", value.date().getTime()); + jgen.writeStringField("uuid", value.uuid().toString()); } } @@ -54,7 +58,10 @@ public class ExampleJsonComponent { @Override protected ExampleCustomObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec, JsonNode tree) throws IOException { - return new ExampleCustomObject(nullSafeValue(tree.get("value"), String.class)); + String value = nullSafeValue(tree.get("value"), String.class); + Date date = nullSafeValue(tree.get("date"), Integer.class, Date::new); + UUID uuid = nullSafeValue(tree.get("uuid"), String.class, UUID::fromString); + return new ExampleCustomObject(value, date, uuid); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jackson/JsonObjectDeserializer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jackson/JsonObjectDeserializer.java index 06ce2a12a5..717b4a70bf 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jackson/JsonObjectDeserializer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jackson/JsonObjectDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -19,6 +19,7 @@ package org.springframework.boot.jackson; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.function.Function; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.ObjectCodec; @@ -72,6 +73,24 @@ public abstract class JsonObjectDeserializer extends com.fasterxml.jackson.da protected abstract T deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec, JsonNode tree) throws IOException; + /** + * Helper method to extract a value from the given {@code jsonNode} or return + * {@code null} when the node itself is {@code null}. + * @param jsonNode the source node (may be {@code null}) + * @param type the data type. May be {@link String}, {@link Boolean}, {@link Long}, + * {@link Integer}, {@link Short}, {@link Double}, {@link Float}, {@link BigDecimal} + * or {@link BigInteger}. + * @param the data type requested + * @param the result type + * @param mapper a mapper to convert the value when it is not {@code null} + * @return the node value or {@code null} + * @since 3.4.0 + */ + protected final R nullSafeValue(JsonNode jsonNode, Class type, Function mapper) { + D value = nullSafeValue(jsonNode, type); + return (value != null) ? mapper.apply(value) : null; + } + /** * Helper method to extract a value from the given {@code jsonNode} or return * {@code null} when the node itself is {@code null}.