Skip to content

Commit 3181608

Browse files
committed
refactor serialize to use jackson directly
1 parent c477064 commit 3181608

File tree

2 files changed

+116
-129
lines changed

2 files changed

+116
-129
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,100 @@
11
package software.amazon.awssdk.enhanced.dynamodb.internal.document;
22

3-
import java.nio.charset.StandardCharsets;
3+
import java.io.IOException;
4+
import java.io.StringWriter;
5+
import java.io.UncheckedIOException;
46
import java.util.Map;
57
import software.amazon.awssdk.annotations.SdkInternalApi;
68
import software.amazon.awssdk.core.SdkBytes;
7-
import software.amazon.awssdk.protocols.json.SdkJsonGenerator;
89
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
910
import software.amazon.awssdk.thirdparty.jackson.core.JsonFactory;
11+
import software.amazon.awssdk.thirdparty.jackson.core.JsonGenerator;
1012

1113
@SdkInternalApi
1214
public final class StrategyJsonSerializer {
1315

14-
private enum JsonSerializationStrategy {
15-
NULL {
16-
@Override
17-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
18-
generator.writeNull();
19-
}
20-
},
21-
STRING {
22-
@Override
23-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
24-
generator.writeValue(av.s());
25-
}
26-
},
27-
NUMBER {
28-
@Override
29-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
30-
generator.writeNumber(av.n());
31-
}
32-
},
33-
BOOLEAN {
34-
@Override
35-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
36-
generator.writeValue(av.bool());
37-
}
38-
},
39-
BYTES {
40-
@Override
41-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
42-
generator.writeValue(av.b().asByteBuffer());
43-
}
44-
},
45-
LIST {
46-
@Override
47-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
48-
generator.writeStartArray();
49-
for (AttributeValue item : av.l()) {
50-
serializeAttributeValue(generator, item);
51-
}
52-
generator.writeEndArray();
53-
}
54-
},
55-
MAP {
56-
@Override
57-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
58-
generator.writeStartObject();
59-
for (Map.Entry<String, AttributeValue> entry : av.m().entrySet()) {
60-
generator.writeFieldName(entry.getKey());
61-
serializeAttributeValue(generator, entry.getValue());
62-
}
63-
generator.writeEndObject();
64-
}
65-
},
66-
STRING_SET {
67-
@Override
68-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
69-
generator.writeStartArray();
70-
for (String s : av.ss()) {
71-
generator.writeValue(s);
72-
}
73-
generator.writeEndArray();
74-
}
75-
},
76-
NUMBER_SET {
77-
@Override
78-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
79-
generator.writeStartArray();
80-
for (String n : av.ns()) {
81-
generator.writeNumber(n);
82-
}
83-
generator.writeEndArray();
84-
}
85-
},
86-
BYTES_SET {
87-
@Override
88-
public void serialize(SdkJsonGenerator generator, AttributeValue av) {
89-
generator.writeStartArray();
90-
for (SdkBytes b : av.bs()) {
91-
generator.writeValue(b.asByteBuffer());
92-
}
93-
generator.writeEndArray();
16+
private StrategyJsonSerializer() {
17+
}
18+
19+
public static String serializeAttributeValueMap(Map<String, AttributeValue> map) {
20+
StringWriter writer = new StringWriter();
21+
try (JsonGenerator generator = new JsonFactory().createGenerator(writer)) {
22+
generator.writeStartObject();
23+
for (Map.Entry<String, AttributeValue> entry : map.entrySet()) {
24+
generator.writeFieldName(entry.getKey());
25+
serializeAttributeValue(generator, entry.getValue());
9426
}
95-
};
27+
generator.writeEndObject();
28+
} catch (IOException e) {
29+
throw new UncheckedIOException(e);
30+
}
31+
return writer.toString();
32+
}
9633

97-
public abstract void serialize(SdkJsonGenerator generator, AttributeValue av);
34+
private static void serializeAttributeValue(JsonGenerator generator, AttributeValue av) throws IOException {
35+
if (av.nul() != null && av.nul()) {
36+
generator.writeNull();
37+
} else if (av.s() != null) {
38+
generator.writeString(av.s());
39+
} else if (av.n() != null) {
40+
generator.writeNumber(av.n());
41+
} else if (av.bool() != null) {
42+
generator.writeBoolean(av.bool());
43+
} else if (av.b() != null) {
44+
generator.writeBinary(av.b().asByteArray());
45+
} else if (av.hasL()) {
46+
serializeList(generator, av);
47+
} else if (av.hasM()) {
48+
serializeMap(generator, av);
49+
} else if (av.hasSs()) {
50+
serializeStringSet(generator, av);
51+
} else if (av.hasNs()) {
52+
serializeNumberSet(generator, av);
53+
} else if (av.hasBs()) {
54+
serializeBytesSet(generator, av);
55+
} else {
56+
throw new IllegalStateException("Unknown AttributeValue type: " + av);
57+
}
9858
}
9959

100-
public static String serializeAttributeValueMap(Map<String, AttributeValue> map) {
101-
SdkJsonGenerator jsonGen = new SdkJsonGenerator(new JsonFactory(), "application/json");
60+
private static void serializeList(JsonGenerator generator, AttributeValue av) throws IOException {
61+
generator.writeStartArray();
62+
for (AttributeValue item : av.l()) {
63+
serializeAttributeValue(generator, item);
64+
}
65+
generator.writeEndArray();
66+
}
10267

103-
jsonGen.writeStartObject();
104-
map.forEach((key, value) -> {
105-
jsonGen.writeFieldName(key);
106-
serializeAttributeValue(jsonGen, value);
107-
});
108-
jsonGen.writeEndObject();
68+
private static void serializeMap(JsonGenerator generator, AttributeValue av) throws IOException {
69+
generator.writeStartObject();
70+
for (Map.Entry<String, AttributeValue> entry : av.m().entrySet()) {
71+
generator.writeFieldName(entry.getKey());
72+
serializeAttributeValue(generator, entry.getValue());
73+
}
74+
generator.writeEndObject();
75+
}
10976

110-
return new String(jsonGen.getBytes(), StandardCharsets.UTF_8);
77+
private static void serializeStringSet(JsonGenerator generator, AttributeValue av) throws IOException {
78+
generator.writeStartArray();
79+
for (String s : av.ss()) {
80+
generator.writeString(s);
81+
}
82+
generator.writeEndArray();
11183
}
11284

113-
public static void serializeAttributeValue(SdkJsonGenerator generator, AttributeValue av) {
114-
JsonSerializationStrategy strategy = getStrategy(av);
115-
strategy.serialize(generator, av);
85+
private static void serializeNumberSet(JsonGenerator generator, AttributeValue av) throws IOException {
86+
generator.writeStartArray();
87+
for (String n : av.ns()) {
88+
generator.writeNumber(n);
89+
}
90+
generator.writeEndArray();
11691
}
11792

118-
private static JsonSerializationStrategy getStrategy(AttributeValue av) {
119-
if (av.nul() != null && av.nul()) return JsonSerializationStrategy.NULL;
120-
if (av.s() != null) return JsonSerializationStrategy.STRING;
121-
if (av.n() != null) return JsonSerializationStrategy.NUMBER;
122-
if (av.bool() != null) return JsonSerializationStrategy.BOOLEAN;
123-
if (av.b() != null) return JsonSerializationStrategy.BYTES;
124-
if (av.hasL()) return JsonSerializationStrategy.LIST;
125-
if (av.hasM()) return JsonSerializationStrategy.MAP;
126-
if (av.hasSs()) return JsonSerializationStrategy.STRING_SET;
127-
if (av.hasNs()) return JsonSerializationStrategy.NUMBER_SET;
128-
if (av.hasBs()) return JsonSerializationStrategy.BYTES_SET;
129-
throw new IllegalStateException("Unknown AttributeValue type: " + av);
93+
private static void serializeBytesSet(JsonGenerator generator, AttributeValue av) throws IOException {
94+
generator.writeStartArray();
95+
for (SdkBytes b : av.bs()) {
96+
generator.writeBinary(b.asByteArray());
97+
}
98+
generator.writeEndArray();
13099
}
131100
}

services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocumentTest.java

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,9 @@ void toJson_numberFormatting_veryLargeNumbers() {
509509
.build();
510510

511511
String json = doc.toJson();
512-
assertThat(json).isNotNull();
512+
assertThat(json).isEqualTo("{\"longMax\":9223372036854775807,\"longMin\":-9223372036854775808,"
513+
+ "\"doubleMax\":1.7976931348623157E308,\"scientific\":1.23E100,"
514+
+ "\"manyDecimals\":1.123456789012345}");
513515
}
514516

515517
@Test
@@ -521,7 +523,7 @@ void toJson_numberFormatting_trailingZeros() {
521523
.build();
522524

523525
String json = doc.toJson();
524-
assertThat(json).isNotNull();
526+
assertThat(json).isEqualTo("{\"twoPointZero\":2.0,\"tenPointZeroZero\":10.0}");
525527
}
526528

527529
@Test
@@ -532,7 +534,7 @@ void toJson_stringEscaping_allControlCharacters() {
532534
.build();
533535

534536
String json = doc.toJson();
535-
assertThat(json).contains("\\n").contains("\\t").contains("\\\"").contains("\\\\");
537+
assertThat(json).isEqualTo("{\"allEscapes\":\"line1\\nline2\\ttab\\\"quote\\\\backslash\\r\\f\"}");
536538
}
537539

538540
@Test
@@ -543,7 +545,7 @@ void toJson_stringEscaping_forwardSlash() {
543545
.build();
544546

545547
String json = doc.toJson();
546-
assertThat(json).isNotNull();
548+
assertThat(json).isEqualTo("{\"slash\":\"path/to/resource\"}");
547549
}
548550

549551
@Test
@@ -554,7 +556,7 @@ void toJson_emptyString() {
554556
.build();
555557

556558
String json = doc.toJson();
557-
assertThat(json).contains("\"empty\":\"\"");
559+
assertThat(json).isEqualTo("{\"empty\":\"\"}");
558560
}
559561

560562
@Test
@@ -565,53 +567,69 @@ void toJson_bytesEncoding_emptyBytes() {
565567
.build();
566568

567569
String json = doc.toJson();
568-
assertThat(json).isNotNull();
570+
assertThat(json).isEqualTo("{\"empty\":\"\"}");
569571
}
570572

571573
@Test
572-
void toJson_bytesEncoding_largeBytes() {
573-
byte[] largeArray = new byte[10000];
574-
Arrays.fill(largeArray, (byte) 65); // Fill with 'A'
575-
574+
void toJson_listWithAllNulls() {
576575
EnhancedDocument doc = EnhancedDocument.builder()
577576
.attributeConverterProviders(defaultProvider())
578-
.putBytes("large", SdkBytes.fromByteArray(largeArray))
577+
.putJson("nullList", "[null,null,null]")
579578
.build();
580579

581580
String json = doc.toJson();
582-
assertThat(json).isNotNull();
581+
assertThat(json).isEqualTo("{\"nullList\":[null,null,null]}");
583582
}
584583

585584
@Test
586-
void toJson_listWithAllNulls() {
585+
void toJson_mapWithNullValues() {
587586
EnhancedDocument doc = EnhancedDocument.builder()
588587
.attributeConverterProviders(defaultProvider())
589-
.putJson("nullList", "[null,null,null]")
588+
.putJson("nullValues", "{\"key1\":null,\"key2\":\"value\",\"key3\":null}")
590589
.build();
591590

592591
String json = doc.toJson();
593-
assertThat(json).contains("[null,null,null]");
592+
assertThat(json).isEqualTo("{\"nullValues\":{\"key1\":null,\"key2\":\"value\",\"key3\":null}}");
594593
}
595594

596595
@Test
597-
void toJson_mapWithSpecialCharKeys() {
596+
void toJson_deeplyNestedStructure() {
597+
String deepJson = "{\"level1\":{\"level2\":{\"level3\":{\"level4\":{\"level5\":{\"level6\":{\"level7\":{\"value\":\"deep\"}}}}}}}}";
598+
598599
EnhancedDocument doc = EnhancedDocument.builder()
599600
.attributeConverterProviders(defaultProvider())
600-
.putJson("specialKeys", "{\"key with spaces\":1,\"key\\\"with\\\"quotes\":2,\"key/with/slash\":3}")
601+
.putJson("nested", deepJson)
601602
.build();
602603

603604
String json = doc.toJson();
604-
assertThat(json).isNotNull();
605+
assertThat(json).isEqualTo("{\"nested\":" + deepJson + "}");
605606
}
606607

607608
@Test
608-
void toJson_mapWithNullValues() {
609+
void toJson_deeplyNestedArrays() {
610+
String deepArrayJson = "[[[[[[\"innermost\"]]]]]]";
611+
609612
EnhancedDocument doc = EnhancedDocument.builder()
610613
.attributeConverterProviders(defaultProvider())
611-
.putJson("nullValues", "{\"key1\":null,\"key2\":\"value\",\"key3\":null}")
614+
.putJson("nestedArrays", deepArrayJson)
612615
.build();
613616

614617
String json = doc.toJson();
615-
assertThat(json).contains("null");
618+
assertThat(json).isEqualTo("{\"nestedArrays\":" + deepArrayJson + "}");
616619
}
620+
621+
@Test
622+
void toJson_emoji() {
623+
624+
String emoji = "{\"smile\":\"Hello 😀 World\"}";
625+
626+
EnhancedDocument doc = EnhancedDocument.builder()
627+
.attributeConverterProviders(defaultProvider())
628+
.putJson("emoji", emoji)
629+
.build();
630+
631+
String json = doc.toJson();
632+
assertThat(json).isEqualTo("{\"emoji\":" + emoji + "}");
633+
}
634+
617635
}

0 commit comments

Comments
 (0)