From 722d0c5a832259427fc2c74707a21b4c7780f863 Mon Sep 17 00:00:00 2001 From: Chris Kolek Date: Mon, 21 Feb 2022 22:09:14 -0500 Subject: [PATCH] Create specific serializer for map values in per-entry serializer lookup --- .../serializers/CustomizedMapSerializer.java | 3 +- .../CustomizedMapSerializerSpec.groovy | 85 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 serde-support/src/test/groovy/io/micronaut/serde/support/serializers/CustomizedMapSerializerSpec.groovy diff --git a/serde-support/src/main/java/io/micronaut/serde/support/serializers/CustomizedMapSerializer.java b/serde-support/src/main/java/io/micronaut/serde/support/serializers/CustomizedMapSerializer.java index 36f2f5152..cdc5721cb 100644 --- a/serde-support/src/main/java/io/micronaut/serde/support/serializers/CustomizedMapSerializer.java +++ b/serde-support/src/main/java/io/micronaut/serde/support/serializers/CustomizedMapSerializer.java @@ -81,7 +81,8 @@ public void serialize(Encoder encoder, EncoderContext context, Argument valueGeneric = (Argument) Argument.of(v.getClass()); - final Serializer valSerializer = context.findSerializer(valueGeneric); + final Serializer valSerializer = context.findSerializer(valueGeneric) + .createSpecific(context, valueGeneric); valSerializer.serialize( childEncoder, context, diff --git a/serde-support/src/test/groovy/io/micronaut/serde/support/serializers/CustomizedMapSerializerSpec.groovy b/serde-support/src/test/groovy/io/micronaut/serde/support/serializers/CustomizedMapSerializerSpec.groovy new file mode 100644 index 000000000..b8dd6b136 --- /dev/null +++ b/serde-support/src/test/groovy/io/micronaut/serde/support/serializers/CustomizedMapSerializerSpec.groovy @@ -0,0 +1,85 @@ +package io.micronaut.serde.support.serializers + +import io.micronaut.core.type.Argument +import io.micronaut.serde.Encoder +import io.micronaut.serde.Serializer +import spock.lang.Specification + +class CustomizedMapSerializerSpec extends Specification { + def 'create specific with generics'() { + given: + def encoder = Mock(Encoder) + encoder.encodeArray(_ as Argument) >> encoder + encoder.encodeObject(_ as Argument) >> encoder + + def defaultSerializer = Mock(Serializer) + defaultSerializer.createSpecific(_ as Serializer.EncoderContext, _ as Argument) >> defaultSerializer + + def context = Mock(Serializer.EncoderContext) + context.findSerializer(Argument.of(String)) >> defaultSerializer + context.findSerializer({Argument a -> List.isAssignableFrom(a.type)}) >> new IterableSerializer<>() + context.findSerializer({Argument a -> Map.isAssignableFrom(a.type)}) >> new CustomizedMapSerializer<>() + + def serializer = new CustomizedMapSerializer() + + def type = Argument.of(Map, String, String) + def specific = serializer.createSpecific(context, type) + when: + specific.serialize(encoder, context, type, [ + val1: 'abc', + val2: '123', + val3: 'true' + ]) + then: + encoder.encodeObject(_ as Argument) + encoder.encodeKey("val1") + encoder.encodeString("abc") + encoder.encodeKey("val2") + encoder.encodeString("123") + encoder.encodeKey("val1") + encoder.encodeString("true") + encoder.finishStructure() + } + + def 'create specific without generics'() { + given: + def encoder = Mock(Encoder) + encoder.encodeArray(_ as Argument) >> encoder + encoder.encodeObject(_ as Argument) >> encoder + + def defaultSerializer = Mock(Serializer) + defaultSerializer.createSpecific(_ as Serializer.EncoderContext, _ as Argument) >> defaultSerializer + + def context = Mock(Serializer.EncoderContext) + context.findSerializer(Argument.of(String)) >> defaultSerializer + context.findSerializer({Argument a -> List.isAssignableFrom(a.type)}) >> new IterableSerializer<>() + context.findSerializer({Argument a -> Map.isAssignableFrom(a.type)}) >> new CustomizedMapSerializer<>() + + def serializer = new CustomizedMapSerializer() + + def type = Argument.of(Map) + def specific = serializer.createSpecific(context, type) + when: + specific.serialize(encoder, context, type, [ + keys: [ + [ + val1: 'abc', + val2: '123', + val3: 'true' + ] + ] + ]) + then: + encoder.encodeObject(_ as Argument) + encoder.encodeKey("keys") + encoder.encodeArray(_ as Argument) + encoder.encodeObject(_ as Argument) + encoder.encodeKey("val1") + encoder.encodeString("abc") + encoder.encodeKey("val2") + encoder.encodeString("123") + encoder.encodeKey("val1") + encoder.encodeString("true") + 3 * encoder.finishStructure() + } +}