Skip to content

Commit c19a319

Browse files
committed
Fix nested dynamic wrapped structures and unions
1 parent b7ba1f7 commit c19a319

File tree

3 files changed

+66
-21
lines changed

3 files changed

+66
-21
lines changed

dynamic-schemas/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ extra["moduleName"] = "software.amazon.smithy.java.dynamicschemas"
99

1010
dependencies {
1111
api(project(":core"))
12+
13+
testImplementation(project(":codecs:json-codec"))
1214
}

dynamic-schemas/src/main/java/software/amazon/smithy/java/dynamicschemas/SchemaInterceptingSerializer.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
import software.amazon.smithy.java.core.schema.Schema;
1414
import software.amazon.smithy.java.core.schema.SerializableStruct;
1515
import software.amazon.smithy.java.core.serde.MapSerializer;
16+
import software.amazon.smithy.java.core.serde.SerializationException;
1617
import software.amazon.smithy.java.core.serde.ShapeSerializer;
1718
import software.amazon.smithy.java.core.serde.document.Document;
19+
import software.amazon.smithy.java.core.serde.document.DocumentParser;
1820
import software.amazon.smithy.model.shapes.ShapeId;
1921
import software.amazon.smithy.model.shapes.ShapeType;
2022

@@ -45,23 +47,38 @@ public <T> void writeList(Schema schema, T listState, int size, BiConsumer<T, Sh
4547

4648
@Override
4749
public <T> void writeMap(Schema schema, T mapState, int size, BiConsumer<T, MapSerializer> consumer) {
48-
var delegateKeySchema = delegateSchema.mapKeyMember();
49-
var delegateValueSchema = delegateSchema.mapValueMember();
50-
delegateSerializer.writeMap(delegateSchema, mapState, size, (s, ms) -> {
51-
consumer.accept(s, new MapSerializer() {
52-
@Override
53-
public <V> void writeEntry(
54-
Schema keySchema,
55-
String key,
56-
V state,
57-
BiConsumer<V, ShapeSerializer> valueSerializer
58-
) {
59-
ms.writeEntry(delegateKeySchema, key, state, (s, ms) -> {
60-
valueSerializer.accept(s, new SchemaInterceptingSerializer(service, delegateValueSchema, ms));
50+
switch (delegateSchema.type()) {
51+
case DOCUMENT, MAP -> {
52+
var delegateKeySchema = delegateSchema.mapKeyMember();
53+
var delegateValueSchema = delegateSchema.mapValueMember();
54+
delegateSerializer.writeMap(delegateSchema, mapState, size, (s, ms) -> {
55+
consumer.accept(s, new MapSerializer() {
56+
@Override
57+
public <V> void writeEntry(
58+
Schema keySchema,
59+
String key,
60+
V state,
61+
BiConsumer<V, ShapeSerializer> valueSerializer
62+
) {
63+
ms.writeEntry(delegateKeySchema, key, state, (s, ms) -> {
64+
valueSerializer.accept(s,
65+
new SchemaInterceptingSerializer(service, delegateValueSchema, ms));
66+
});
67+
}
6168
});
62-
}
63-
});
64-
});
69+
});
70+
}
71+
case STRUCTURE, UNION -> {
72+
var parser = new DocumentParser();
73+
parser.writeMap(schema, mapState, size, consumer);
74+
var struct = parser.getResult();
75+
var wrappedStruct = new WrappedDocument(delegateSchema, Document.of(struct), service);
76+
delegateSerializer.writeStruct(delegateSchema, wrappedStruct);
77+
}
78+
default -> {
79+
throw new SerializationException("Expected a map, structure, or union, but found " + delegateSchema);
80+
}
81+
}
6582
}
6683

6784
@Override

dynamic-schemas/src/test/java/software/amazon/smithy/java/dynamicschemas/SchemaGuidedDocumentBuilderTest.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
import static org.hamcrest.MatcherAssert.assertThat;
99
import static org.hamcrest.Matchers.equalTo;
10-
import static org.hamcrest.Matchers.not;
11-
import static org.hamcrest.Matchers.nullValue;
1210

1311
import java.math.BigDecimal;
1412
import java.math.BigInteger;
@@ -24,15 +22,13 @@
2422
import org.junit.jupiter.params.provider.MethodSource;
2523
import software.amazon.smithy.java.core.schema.PreludeSchemas;
2624
import software.amazon.smithy.java.core.schema.Schema;
27-
import software.amazon.smithy.java.core.schema.SerializableStruct;
2825
import software.amazon.smithy.java.core.serde.InterceptingSerializer;
29-
import software.amazon.smithy.java.core.serde.ShapeDeserializer;
3026
import software.amazon.smithy.java.core.serde.ShapeSerializer;
3127
import software.amazon.smithy.java.core.serde.SpecificShapeDeserializer;
3228
import software.amazon.smithy.java.core.serde.SpecificShapeSerializer;
3329
import software.amazon.smithy.java.core.serde.document.Document;
3430
import software.amazon.smithy.java.core.serde.document.DocumentDeserializer;
35-
import software.amazon.smithy.java.core.serde.document.DocumentUtils;
31+
import software.amazon.smithy.java.json.JsonCodec;
3632
import software.amazon.smithy.model.Model;
3733
import software.amazon.smithy.model.shapes.ShapeId;
3834
import software.amazon.smithy.model.shapes.ShapeType;
@@ -96,6 +92,16 @@ enum MyEnum {
9692
foo: String
9793
baz: SimpleStruct
9894
}
95+
96+
map StructMap {
97+
key: String
98+
value: Foo
99+
}
100+
101+
structure Foo {
102+
@jsonName("B")
103+
b: String
104+
}
99105
""")
100106
.assemble()
101107
.unwrap();
@@ -265,6 +271,26 @@ public void throwsWhenNoValueSetForUnion() {
265271
Assertions.assertThrows(IllegalArgumentException.class, builder::build);
266272
}
267273

274+
@Test
275+
public void worksWithMapOfStructure() {
276+
var source = Document.ofObject(Map.of("a", Document.ofObject(Map.of("b", "str"))));
277+
278+
var converter = new SchemaConverter(model);
279+
var schema = converter.getSchema(model.expectShape(ShapeId.from("smithy.example#StructMap")));
280+
281+
var builder = SchemaConverter.createDocumentBuilder(schema, ShapeId.from("smithy.example#StructMap"));
282+
source.deserializeInto(builder);
283+
284+
var result = builder.build();
285+
286+
assertThat(result.asObject(), equalTo(source.asObject()));
287+
assertThat(result.schema(), equalTo(schema));
288+
289+
var codec = JsonCodec.builder().useJsonName(true).build();
290+
291+
assertThat(codec.serializeToString(result), equalTo("{\"a\":{\"B\":\"str\"}}"));
292+
}
293+
268294
static List<Arguments> deserializesShapesProvider() {
269295
return List.of(
270296
Arguments.of("MyDocument", Document.ofObject(Map.of("a", "b"))),

0 commit comments

Comments
 (0)