diff --git a/spring-geode/src/main/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverter.java b/spring-geode/src/main/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverter.java index 87c03a71..ca5bbfff 100644 --- a/spring-geode/src/main/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverter.java +++ b/spring-geode/src/main/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverter.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.geode.data.json.converter.ObjectToJsonConverter; +import org.springframework.geode.pdx.PdxInstanceWrapper; import org.springframework.lang.NonNull; import org.springframework.util.Assert; @@ -41,7 +42,7 @@ import org.springframework.util.Assert; */ public class JacksonObjectToJsonConverter implements ObjectToJsonConverter { - protected static final String AT_TYPE_METADATA_PROPERTY_NAME = "@type"; + protected static final String AT_TYPE_METADATA_PROPERTY_NAME = PdxInstanceWrapper.AT_TYPE_FIELD_NAME; /** * Converts the given {@link Object} into {@link String JSON}. @@ -57,7 +58,7 @@ public class JacksonObjectToJsonConverter implements ObjectToJsonConverter { Assert.notNull(source, "Source object to convert must not be null"); try { - return newObjectMapper(source).writeValueAsString(source); + return convertObjectToJson(source); } catch (JsonProcessingException cause) { throw new ConversionFailedException(TypeDescriptor.forObject(source), TypeDescriptor.valueOf(String.class), @@ -65,6 +66,24 @@ public class JacksonObjectToJsonConverter implements ObjectToJsonConverter { } } + /** + * Converts the given {@link Object} into {@link String JSON}. + * + * @param source {@link Object} to convert to {@link String JSON}; must not be {@literal null}. + * @return {@link String JSON} generated from the given {@link Object}. + * @throws IllegalArgumentException if {@link Object source} is {@literal null}. + * @throws JsonProcessingException if the generation of {@link String JSON} from the given {@link Object} + * results in an error. + * @see com.fasterxml.jackson.databind.ObjectMapper#writeValueAsString(Object) + * @see #newObjectMapper(Object) + */ + protected @NonNull String convertObjectToJson(@NonNull Object source) throws JsonProcessingException { + + Assert.notNull(source, "Source object to convert must not be null"); + + return newObjectMapper(source).writeValueAsString(source); + } + /** * Constructs a new instance of the Jackson {@link ObjectMapper} class. * @@ -75,10 +94,21 @@ public class JacksonObjectToJsonConverter implements ObjectToJsonConverter { Assert.notNull(target, "Target object must not be null"); - return new ObjectMapper() + return newObjectMapper() .addMixIn(target.getClass(), ObjectTypeMetadataMixin.class) .configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true) - .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true); + .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) + .findAndRegisterModules(); + } + + /** + * Constructs a new instance of Jackson's {@link ObjectMapper}. + * + * @return a new instance of Jackson's {@link ObjectMapper}; never {@literal null}. + * @see com.fasterxml.jackson.databind.ObjectMapper + */ + @NonNull ObjectMapper newObjectMapper() { + return new ObjectMapper(); } @JsonTypeInfo( diff --git a/spring-geode/src/test/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverterUnitTests.java b/spring-geode/src/test/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverterUnitTests.java index 6abf87ee..c21844e7 100644 --- a/spring-geode/src/test/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverterUnitTests.java +++ b/spring-geode/src/test/java/org/springframework/geode/data/json/converter/support/JacksonObjectToJsonConverterUnitTests.java @@ -17,6 +17,7 @@ package org.springframework.geode.data.json.converter.support; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -25,6 +26,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; @@ -44,6 +46,7 @@ import example.app.crm.model.Customer; * @author John Blum * @see org.junit.Test * @see org.mockito.Mockito + * @see com.fasterxml.jackson.databind.ObjectMapper * @see org.springframework.geode.data.json.converter.support.JacksonObjectToJsonConverter * @since 1.3.0 */ @@ -139,12 +142,29 @@ public class JacksonObjectToJsonConverterUnitTests { Object target = Customer.newCustomer(1L, "Jon Doe"); - ObjectMapper objectMapper = new JacksonObjectToJsonConverter().newObjectMapper(target); + ObjectMapper mockObjectMapper = mock(ObjectMapper.class); + + JacksonObjectToJsonConverter converter = spy(new JacksonObjectToJsonConverter()); + + doReturn(mockObjectMapper).when(converter).newObjectMapper(); + doReturn(mockObjectMapper).when(mockObjectMapper).addMixIn(any(), any()); + doReturn(mockObjectMapper).when(mockObjectMapper).configure(any(JsonGenerator.Feature.class), anyBoolean()); + doReturn(mockObjectMapper).when(mockObjectMapper).configure(any(MapperFeature.class), anyBoolean()); + doReturn(mockObjectMapper).when(mockObjectMapper).findAndRegisterModules(); + + ObjectMapper objectMapper = converter.newObjectMapper(target); assertThat(objectMapper).isNotNull(); - assertThat(objectMapper.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)).isTrue(); - assertThat(objectMapper.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)).isTrue(); - assertThat(objectMapper.getSerializationConfig().findMixInClassFor(target.getClass())) - .isEqualTo(JacksonObjectToJsonConverter.ObjectTypeMetadataMixin.class); + + verify(converter, times(1)).newObjectMapper(); + + verify(mockObjectMapper, times(1)) + .addMixIn(eq(target.getClass()), eq(JacksonObjectToJsonConverter.ObjectTypeMetadataMixin.class)); + verify(mockObjectMapper, times(1)) + .configure(eq(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN), eq(true)); + verify(mockObjectMapper, times(1)) + .configure(eq(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY), eq(true)); + verify(mockObjectMapper, times(1)).findAndRegisterModules(); + verifyNoMoreInteractions(mockObjectMapper); } }