diff --git a/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/CustomStringSerdeSpec.groovy b/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/CustomStringSerdeSpec.groovy new file mode 100644 index 000000000..f1ef335eb --- /dev/null +++ b/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/CustomStringSerdeSpec.groovy @@ -0,0 +1,60 @@ +package io.micronaut.serde.jackson + +import io.micronaut.core.annotation.NonNull +import io.micronaut.core.annotation.Order +import io.micronaut.core.type.Argument +import io.micronaut.core.util.StringUtils +import io.micronaut.serde.Decoder +import io.micronaut.serde.Deserializer +import io.micronaut.serde.Encoder +import io.micronaut.serde.ObjectMapper +import io.micronaut.serde.Serde +import io.micronaut.serde.Serializer +import io.micronaut.serde.annotation.Serdeable +import io.micronaut.test.annotation.MockBean +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@MicronautTest +class CustomStringSerdeSpec extends Specification { + + @Inject ObjectMapper objectMapper + + void "test custom string encoder"() { + expect: + objectMapper.writeValueAsString(new Test(name: "Fred")) == '{"name":"derF"}' + objectMapper.writeValueAsString(new Test(name: "")) == '{"name":null}' + objectMapper.writeValueAsString(new Test(name: " ")) == '{"name":null}' + objectMapper.readValue('{"name":"derF"}', Test).name == "Fred" + + } + + @Serdeable + static class Test { + String name + } + + @MockBean + Serde stringSerde() { + return new Serde() { + @Override + String deserialize(@NonNull Decoder decoder, @NonNull Deserializer.DecoderContext context, @NonNull Argument type) throws IOException { + if (decoder.decodeNull()) { + return null + } else { + return decoder.decodeString().reverse() + } + } + + @Override + void serialize(@NonNull Encoder encoder, @NonNull Serializer.EncoderContext context, @NonNull Argument type, @NonNull String value) throws IOException { + if (StringUtils.isEmpty(value.trim())) { + encoder.encodeNull() + } else { + encoder.encodeString(value.reverse()) + } + } + } + } +} diff --git a/serde-support/src/main/java/io/micronaut/serde/support/DefaultSerdeRegistry.java b/serde-support/src/main/java/io/micronaut/serde/support/DefaultSerdeRegistry.java index 6e899bc28..99cf98e0a 100644 --- a/serde-support/src/main/java/io/micronaut/serde/support/DefaultSerdeRegistry.java +++ b/serde-support/src/main/java/io/micronaut/serde/support/DefaultSerdeRegistry.java @@ -180,8 +180,16 @@ private void registerPrimitiveSerdes() { } private void registerBuiltInSerdes() { - this.deserializerMap.put(new TypeKey(Argument.STRING), - (NullableDeserializer) (decoder, decoderContext, type) -> decoder.decodeString()); + if (!this.deserializerDefMap.containsKey(String.class)) { + TypeKey tk = new TypeKey(Argument.STRING); + this.deserializerMap.put(tk, + (NullableDeserializer) (decoder, decoderContext, type) -> decoder.decodeString()); + } + if (!this.deserializerDefMap.containsKey(CharSequence.class)) { + TypeKey tk = new TypeKey(Argument.of(CharSequence.class)); + this.deserializerMap.put(tk, + (NullableDeserializer) (decoder, decoderContext, type) -> decoder.decodeString()); + } Stream.of( new IntegerSerde(), new LongSerde(), @@ -214,8 +222,12 @@ private void registerBuiltInSerdes() { private void register(SerdeRegistrar serdeRegistrar) { for (Argument type : serdeRegistrar.getTypes()) { final TypeKey typeEntry = new TypeKey(type); - DefaultSerdeRegistry.this.deserializerMap.put(typeEntry, serdeRegistrar); - DefaultSerdeRegistry.this.serializerMap.put(typeEntry, serdeRegistrar); + if (!DefaultSerdeRegistry.this.deserializerMap.containsKey(typeEntry)) { + DefaultSerdeRegistry.this.deserializerMap.put(typeEntry, serdeRegistrar); + } + if (!DefaultSerdeRegistry.this.serializerMap.containsKey(typeEntry)) { + DefaultSerdeRegistry.this.serializerMap.put(typeEntry, serdeRegistrar); + } } } diff --git a/serde-support/src/main/java/io/micronaut/serde/support/deserializers/CoreDeserializers.java b/serde-support/src/main/java/io/micronaut/serde/support/deserializers/CoreDeserializers.java index a0c6fb528..352d646e6 100644 --- a/serde-support/src/main/java/io/micronaut/serde/support/deserializers/CoreDeserializers.java +++ b/serde-support/src/main/java/io/micronaut/serde/support/deserializers/CoreDeserializers.java @@ -48,17 +48,6 @@ @Factory public class CoreDeserializers { - /** - * Deserializes string types. - * - * @return The string deserializer - */ - @Singleton - @NonNull - protected Deserializer stringDeserializer() { - return new StringDeserializer(); - } - /** * Deserializes array lists. * @@ -189,22 +178,6 @@ protected Deserializer> optionalDeserializer() { return new OptionalDeserializer<>(); } - private static class StringDeserializer implements Deserializer { - - @Override - public String deserialize(Decoder decoder, DecoderContext decoderContext, Argument type) throws IOException { - if (decoder.decodeNull()) { - return null; - } - return decoder.decodeString(); - } - - @Override - public boolean allowNull() { - return true; - } - } - private static class OptionalDeserializer implements CustomizableDeserializer> { @Override diff --git a/settings.gradle.kts b/settings.gradle.kts index 85827110f..fb4bf094f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,7 +6,7 @@ pluginManagement { } plugins { - id("io.micronaut.build.shared.settings") version "5.3.16" + id("io.micronaut.build.shared.settings") version "5.4.9" } enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")