From 20e67b07b5d5e301aabb99dc02388e5ca4ffaaa6 Mon Sep 17 00:00:00 2001 From: yawkat Date: Wed, 27 Sep 2023 12:59:19 +0200 Subject: [PATCH] Builder token buffer support This fixes the combination of property-based subtyping and builders. --- .../serde/jackson/builder/BuilderSpec.groovy | 12 ++++++ .../jackson/builder/TestBuildSubtype2.java | 36 +++++++++++++++++ .../jackson/builder/TestBuildSupertype2.java | 39 +++++++++++++++++++ .../SpecificObjectDeserializer.java | 17 ++++++++ 4 files changed, 104 insertions(+) create mode 100644 serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSubtype2.java create mode 100644 serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSupertype2.java diff --git a/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/builder/BuilderSpec.groovy b/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/builder/BuilderSpec.groovy index df75b9ce0..79b093a37 100644 --- a/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/builder/BuilderSpec.groovy +++ b/serde-jackson/src/test/groovy/io/micronaut/serde/jackson/builder/BuilderSpec.groovy @@ -56,4 +56,16 @@ class BuilderSpec extends Specification { value.foo == 'fizz' value.bar == 'buzz' } + + void "test deserialize builder on supertype"() { + given: + def json = '{"foo":"fizz"}' + + when: + def value = objectMapper.readValue(json, TestBuildSupertype2) + + then: + value.getClass() == TestBuildSupertype2 + value.foo == 'fizz' + } } diff --git a/serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSubtype2.java b/serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSubtype2.java new file mode 100644 index 000000000..99d6ca3be --- /dev/null +++ b/serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSubtype2.java @@ -0,0 +1,36 @@ +package io.micronaut.serde.jackson.builder; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +@JsonDeserialize(builder = TestBuildSubtype2.Builder.class) +public class TestBuildSubtype2 extends TestBuildSupertype2 { + private final String bar; + + private TestBuildSubtype2(String foo, String bar) { + super(foo); + this.bar = bar; + } + + public String getBar() { + return bar; + } + + public static class Builder { + private String foo; + private String bar; + + public Builder foo(String foo) { + this.foo = foo; + return this; + } + + public Builder bar(String bar) { + this.bar = bar; + return this; + } + + public TestBuildSubtype2 build() { + return new TestBuildSubtype2(foo, bar); + } + } +} diff --git a/serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSupertype2.java b/serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSupertype2.java new file mode 100644 index 000000000..75050f1b2 --- /dev/null +++ b/serde-jackson/src/test/java/io/micronaut/serde/jackson/builder/TestBuildSupertype2.java @@ -0,0 +1,39 @@ +package io.micronaut.serde.jackson.builder; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +@JsonSubTypes({ + @JsonSubTypes.Type(value = TestBuildSubtype2.class, name = "sub") +}) +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.PROPERTY, + defaultImpl = TestBuildSupertype2.class +) +@JsonDeserialize(builder = TestBuildSupertype2.Builder.class) +public class TestBuildSupertype2 { + private final String foo; + + TestBuildSupertype2(String foo) { + this.foo = foo; + } + + public String getFoo() { + return foo; + } + + public static class Builder { + private String foo; + + public Builder foo(String foo) { + this.foo = foo; + return this; + } + + public TestBuildSupertype2 build() { + return new TestBuildSupertype2(foo); + } + } +} diff --git a/serde-support/src/main/java/io/micronaut/serde/support/deserializers/SpecificObjectDeserializer.java b/serde-support/src/main/java/io/micronaut/serde/support/deserializers/SpecificObjectDeserializer.java index feae4e1e5..223718371 100644 --- a/serde-support/src/main/java/io/micronaut/serde/support/deserializers/SpecificObjectDeserializer.java +++ b/serde-support/src/main/java/io/micronaut/serde/support/deserializers/SpecificObjectDeserializer.java @@ -340,6 +340,23 @@ public Object deserialize(Decoder decoder, DecoderContext decoderContext, Argume throw new SerdeException(PREFIX_UNABLE_TO_DESERIALIZE_TYPE + type + "]: " + e.getMessage(), e); } if (hasProperties) { + if (tokenBuffer != null) { + for (TokenBuffer buffer : tokenBuffer) { + final DeserBean.DerProperty property = readProperties.consume(buffer.name); + if (property != null) { + property.deserializeAndCallBuilder(buffer.decoder, decoderContext, builder); + } else { + skipOrSetAny( + decoderContext, + buffer.decoder, + buffer.name, + anyValues, + ignoreUnknown, + type + ); + } + } + } while (true) { final String prop = objectDecoder.decodeKey(); if (prop == null) {