Skip to content

Commit 2ef01a1

Browse files
committed
Delegate writing to gson as well, add tests for writing and parsing all types and null
1 parent 5c1ab08 commit 2ef01a1

File tree

8 files changed

+170
-43
lines changed

8 files changed

+170
-43
lines changed

components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonParseNode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
/** ParseNode implementation for JSON */
3030
public class JsonParseNode implements ParseNode {
31-
protected final JsonElement currentNode;
32-
protected final Gson gson;
31+
private final JsonElement currentNode;
32+
private final Gson gson;
3333

3434
/**
3535
* Creates a new instance of the JsonParseNode class.
@@ -54,7 +54,7 @@ public JsonParseNode(@Nonnull final JsonElement node, @Nonnull final Gson gson)
5454
* @param node the node to wrap.
5555
* @return the newly created {@link JsonParseNode}.
5656
*/
57-
@Nonnull protected JsonParseNode createNewNode(@Nonnull JsonElement node) {
57+
@Nonnull private JsonParseNode createNewNode(@Nonnull JsonElement node) {
5858
return new JsonParseNode(node, gson);
5959
}
6060

@@ -128,7 +128,7 @@ public JsonParseNode(@Nonnull final JsonElement node, @Nonnull final Gson gson)
128128
return gson.fromJson(currentNode, PeriodAndDuration.class);
129129
}
130130

131-
@Nullable protected <T> T getPrimitiveValue(
131+
@Nullable private <T> T getPrimitiveValue(
132132
@Nonnull final Class<T> targetClass, @Nonnull final JsonParseNode itemNode) {
133133
return gson.fromJson(itemNode.currentNode, targetClass);
134134
}

components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonParseNodeFactory.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,6 @@ public JsonParseNodeFactory(@Nonnull Gson gson) {
3636

3737
private static final String validContentType = "application/json";
3838

39-
/**
40-
* @return the {@link Gson} instance to use for parsing value types.
41-
*/
42-
@Nonnull public Gson getGson() {
43-
return gson;
44-
}
45-
4639
/** {@inheritDoc} */
4740
@Override
4841
@Nonnull public ParseNode getParseNode(

components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonSerializationWriter.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void writeStringValue(@Nullable final String key, @Nullable final String
5858
if (key != null && !key.isEmpty()) {
5959
writer.name(key);
6060
}
61-
writer.value(value);
61+
gson.getAdapter(String.class).write(writer, value);
6262
} catch (IOException ex) {
6363
throw new RuntimeException("could not serialize value", ex);
6464
}
@@ -70,7 +70,7 @@ public void writeBooleanValue(@Nullable final String key, @Nullable final Boolea
7070
if (key != null && !key.isEmpty()) {
7171
writer.name(key);
7272
}
73-
writer.value(value);
73+
gson.getAdapter(Boolean.class).write(writer, value);
7474
} catch (IOException ex) {
7575
throw new RuntimeException("could not serialize value", ex);
7676
}
@@ -82,7 +82,7 @@ public void writeShortValue(@Nullable final String key, @Nullable final Short va
8282
if (key != null && !key.isEmpty()) {
8383
writer.name(key);
8484
}
85-
writer.value(value);
85+
gson.getAdapter(Short.class).write(writer, value);
8686
} catch (IOException ex) {
8787
throw new RuntimeException("could not serialize value", ex);
8888
}
@@ -94,7 +94,7 @@ public void writeByteValue(@Nullable final String key, @Nullable final Byte valu
9494
if (key != null && !key.isEmpty()) {
9595
writer.name(key);
9696
}
97-
writer.value(value);
97+
gson.getAdapter(Byte.class).write(writer, value);
9898
} catch (IOException ex) {
9999
throw new RuntimeException("could not serialize value", ex);
100100
}
@@ -106,7 +106,7 @@ public void writeBigDecimalValue(@Nullable final String key, @Nullable final Big
106106
if (key != null && !key.isEmpty()) {
107107
writer.name(key);
108108
}
109-
writer.value(value);
109+
gson.getAdapter(BigDecimal.class).write(writer, value);
110110
} catch (IOException ex) {
111111
throw new RuntimeException("could not serialize value", ex);
112112
}
@@ -118,7 +118,7 @@ public void writeIntegerValue(@Nullable final String key, @Nullable final Intege
118118
if (key != null && !key.isEmpty()) {
119119
writer.name(key);
120120
}
121-
writer.value(value);
121+
gson.getAdapter(Integer.class).write(writer, value);
122122
} catch (IOException ex) {
123123
throw new RuntimeException("could not serialize value", ex);
124124
}
@@ -130,7 +130,7 @@ public void writeFloatValue(@Nullable final String key, @Nullable final Float va
130130
if (key != null && !key.isEmpty()) {
131131
writer.name(key);
132132
}
133-
writer.value(value);
133+
gson.getAdapter(Float.class).write(writer, value);
134134
} catch (IOException ex) {
135135
throw new RuntimeException("could not serialize value", ex);
136136
}
@@ -142,7 +142,7 @@ public void writeDoubleValue(@Nullable final String key, @Nullable final Double
142142
if (key != null && !key.isEmpty()) {
143143
writer.name(key);
144144
}
145-
writer.value(value);
145+
gson.getAdapter(Double.class).write(writer, value);
146146
} catch (IOException ex) {
147147
throw new RuntimeException("could not serialize value", ex);
148148
}
@@ -154,7 +154,7 @@ public void writeLongValue(@Nullable final String key, @Nullable final Long valu
154154
if (key != null && !key.isEmpty()) {
155155
writer.name(key);
156156
}
157-
writer.value(value);
157+
gson.getAdapter(Long.class).write(writer, value);
158158
} catch (IOException ex) {
159159
throw new RuntimeException("could not serialize value", ex);
160160
}

components/serialization/json/src/main/java/com/microsoft/kiota/serialization/JsonSerializationWriterFactory.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ public JsonSerializationWriterFactory(@Nonnull Gson gson) {
3131

3232
private static final String validContentType = "application/json";
3333

34-
/**
35-
* @return the {@link Gson} instance to use for writing value types.
36-
*/
37-
@Nonnull public Gson getGson() {
38-
return gson;
39-
}
40-
4134
/** {@inheritDoc} */
4235
@Override
4336
@Nonnull public SerializationWriter getSerializationWriter(@Nonnull final String contentType) {

components/serialization/json/src/test/java/com/microsoft/kiota/serialization/JsonSerializationWriterTests.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
package com.microsoft.kiota.serialization;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNull;
45

56
import com.microsoft.kiota.Compatibility;
7+
import com.microsoft.kiota.PeriodAndDuration;
68
import com.microsoft.kiota.serialization.mocks.MyEnum;
79
import com.microsoft.kiota.serialization.mocks.TestEntity;
810
import com.microsoft.kiota.serialization.mocks.UntypedTestEntity;
911

1012
import org.junit.jupiter.api.Test;
1113

1214
import java.io.IOException;
15+
import java.math.BigDecimal;
16+
import java.time.Duration;
17+
import java.time.LocalDate;
18+
import java.time.LocalTime;
1319
import java.time.OffsetDateTime;
20+
import java.time.Period;
1421
import java.util.ArrayList;
1522
import java.util.Arrays;
1623
import java.util.HashMap;
1724
import java.util.List;
25+
import java.util.UUID;
1826

1927
class JsonSerializationWriterTests {
2028

@@ -225,4 +233,58 @@ void writesSampleObjectValueWithUntypedProperties() throws IOException {
225233
assertEquals(expectedString, serializedJsonString);
226234
}
227235
}
236+
237+
@Test
238+
void parseWrittenValues() throws IOException {
239+
writeAndParse(
240+
ParseNode::getStringValue, SerializationWriter::writeStringValue, "just a string");
241+
writeAndParse(ParseNode::getBooleanValue, SerializationWriter::writeBooleanValue, true);
242+
writeAndParse(ParseNode::getByteValue, SerializationWriter::writeByteValue, (byte) 3);
243+
writeAndParse(ParseNode::getShortValue, SerializationWriter::writeShortValue, (short) 42);
244+
writeAndParse(
245+
ParseNode::getBigDecimalValue,
246+
SerializationWriter::writeBigDecimalValue,
247+
new BigDecimal(123456789L));
248+
writeAndParse(ParseNode::getIntegerValue, SerializationWriter::writeIntegerValue, 54321);
249+
writeAndParse(
250+
ParseNode::getFloatValue, SerializationWriter::writeFloatValue, (float) 67.89);
251+
writeAndParse(ParseNode::getDoubleValue, SerializationWriter::writeDoubleValue, 3245.12356);
252+
writeAndParse(ParseNode::getLongValue, SerializationWriter::writeLongValue, -543219876L);
253+
writeAndParse(
254+
ParseNode::getUUIDValue, SerializationWriter::writeUUIDValue, UUID.randomUUID());
255+
writeAndParse(
256+
ParseNode::getOffsetDateTimeValue,
257+
SerializationWriter::writeOffsetDateTimeValue,
258+
OffsetDateTime.now());
259+
writeAndParse(
260+
ParseNode::getLocalDateValue,
261+
SerializationWriter::writeLocalDateValue,
262+
LocalDate.now());
263+
writeAndParse(
264+
ParseNode::getLocalTimeValue,
265+
SerializationWriter::writeLocalTimeValue,
266+
LocalTime.now());
267+
writeAndParse(
268+
ParseNode::getPeriodAndDurationValue,
269+
SerializationWriter::writePeriodAndDurationValue,
270+
PeriodAndDuration.of(Period.ofYears(3), Duration.ofHours(6)));
271+
}
272+
273+
private <T> void writeAndParse(
274+
TestParsable.ParseMethod<T> parseMethod,
275+
TestParsable.WriteMethod<T> writeMethod,
276+
T value)
277+
throws IOException {
278+
var testParsable = new TestParsable<>(parseMethod, writeMethod, value);
279+
var writer = new JsonSerializationWriter(DefaultGsonBuilder.getDefaultInstance());
280+
writer.writeObjectValue(null, testParsable);
281+
282+
var parseNodeFactory = new JsonParseNodeFactory(DefaultGsonBuilder.getDefaultInstance());
283+
var parseNode =
284+
parseNodeFactory.getParseNode("application/json", writer.getSerializedContent());
285+
var result = parseNode.getObjectValue(TestParsable.factory(parseMethod, writeMethod));
286+
assertEquals(value, result.getRealValue());
287+
assertNull(result.getNullValue());
288+
writer.close();
289+
}
228290
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.microsoft.kiota.serialization;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import java.util.function.Consumer;
6+
7+
public class TestParsable<T> implements Parsable {
8+
@FunctionalInterface
9+
public interface WriteMethod<V> {
10+
public void write(SerializationWriter writer, String key, V value);
11+
}
12+
13+
@FunctionalInterface
14+
public interface ParseMethod<V> {
15+
public V parse(ParseNode parseNode);
16+
}
17+
18+
private T realValue;
19+
20+
private T nullValue;
21+
22+
private final ParseMethod<T> parseMethod;
23+
24+
private final WriteMethod<T> writeMethod;
25+
26+
public TestParsable(ParseMethod<T> parseMethod, WriteMethod<T> writeMethod) {
27+
this(parseMethod, writeMethod, null);
28+
}
29+
30+
public TestParsable(ParseMethod<T> parseMethod, WriteMethod<T> writeMethod, T value) {
31+
this.parseMethod = parseMethod;
32+
this.writeMethod = writeMethod;
33+
this.realValue = value;
34+
}
35+
36+
@Override
37+
public Map<String, Consumer<ParseNode>> getFieldDeserializers() {
38+
final HashMap<String, java.util.function.Consumer<ParseNode>> deserializerMap =
39+
new HashMap<String, java.util.function.Consumer<ParseNode>>(2);
40+
deserializerMap.put(
41+
"realValue",
42+
(n) -> {
43+
this.realValue = parseMethod.parse(n);
44+
});
45+
deserializerMap.put(
46+
"nullValue",
47+
(n) -> {
48+
this.nullValue = parseMethod.parse(n);
49+
});
50+
return deserializerMap;
51+
}
52+
53+
@Override
54+
public void serialize(SerializationWriter writer) {
55+
writeMethod.write(writer, "realValue", realValue);
56+
writeMethod.write(writer, "nullValue", nullValue);
57+
}
58+
59+
public T getRealValue() {
60+
return realValue;
61+
}
62+
63+
public T getNullValue() {
64+
return nullValue;
65+
}
66+
67+
public static <T> ParsableFactory<TestParsable<T>> factory(
68+
ParseMethod<T> parseMethod, WriteMethod<T> writeMethod) {
69+
return (n) -> new TestParsable<T>(parseMethod, writeMethod);
70+
}
71+
}

components/serialization/json/src/test/java/com/microsoft/kiota/serialization/mocks/IntersectionTypeMock.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.microsoft.kiota.serialization.mocks;
22

3+
import com.google.gson.JsonSyntaxException;
34
import com.microsoft.kiota.serialization.ComposedTypeWrapper;
45
import com.microsoft.kiota.serialization.Parsable;
56
import com.microsoft.kiota.serialization.ParseNode;
@@ -21,16 +22,18 @@ public class IntersectionTypeMock implements Parsable, ComposedTypeWrapper {
2122
@jakarta.annotation.Nonnull final ParseNode parseNode) {
2223
Objects.requireNonNull(parseNode);
2324
final var result = new IntersectionTypeMock();
24-
if (parseNode.getStringValue() != null) {
25+
try {
2526
result.setStringValue(parseNode.getStringValue());
26-
} else if (parseNode.getCollectionOfObjectValues(TestEntity::createFromDiscriminatorValue)
27-
!= null) {
28-
result.setComposedType3(
29-
parseNode.getCollectionOfObjectValues(
30-
TestEntity::createFromDiscriminatorValue));
31-
} else {
32-
result.setComposedType1(new TestEntity());
33-
result.setComposedType2(new SecondTestEntity());
27+
} catch (JsonSyntaxException e) {
28+
if (parseNode.getCollectionOfObjectValues(TestEntity::createFromDiscriminatorValue)
29+
!= null) {
30+
result.setComposedType3(
31+
parseNode.getCollectionOfObjectValues(
32+
TestEntity::createFromDiscriminatorValue));
33+
} else {
34+
result.setComposedType1(new TestEntity());
35+
result.setComposedType2(new SecondTestEntity());
36+
}
3437
}
3538
return result;
3639
}

components/serialization/json/src/test/java/com/microsoft/kiota/serialization/mocks/UnionTypeMock.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.microsoft.kiota.serialization.mocks;
22

3+
import com.google.gson.JsonSyntaxException;
34
import com.microsoft.kiota.serialization.ComposedTypeWrapper;
45
import com.microsoft.kiota.serialization.Parsable;
56
import com.microsoft.kiota.serialization.ParseNode;
@@ -28,13 +29,17 @@ public class UnionTypeMock implements Parsable, ComposedTypeWrapper {
2829
} else if ("#microsoft.graph.secondTestEntity".equalsIgnoreCase(mappingValue)) {
2930
result.setComposedType2(new SecondTestEntity());
3031
}
31-
} else if (parseNode.getStringValue() != null) {
32-
result.setStringValue(parseNode.getStringValue());
33-
} else if (parseNode.getCollectionOfObjectValues(TestEntity::createFromDiscriminatorValue)
34-
!= null) {
35-
result.setComposedType3(
36-
parseNode.getCollectionOfObjectValues(
37-
TestEntity::createFromDiscriminatorValue));
32+
} else {
33+
try {
34+
result.setStringValue(parseNode.getStringValue());
35+
} catch (JsonSyntaxException e) {
36+
if (parseNode.getCollectionOfObjectValues(TestEntity::createFromDiscriminatorValue)
37+
!= null) {
38+
result.setComposedType3(
39+
parseNode.getCollectionOfObjectValues(
40+
TestEntity::createFromDiscriminatorValue));
41+
}
42+
}
3843
}
3944
return result;
4045
}

0 commit comments

Comments
 (0)