Skip to content

Commit a50429b

Browse files
committed
fix serialization of Void so illegal access warnings do not appear with Java 9
1 parent 613cbe2 commit a50429b

File tree

4 files changed

+161
-109
lines changed

4 files changed

+161
-109
lines changed

src/main/java/com/microsoft/graph/serializer/FallBackEnumTypeAdapter.java

Lines changed: 0 additions & 105 deletions
This file was deleted.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// ------------------------------------------------------------------------------
2+
// Copyright (c) 2017 Microsoft Corporation
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in
12+
// all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
// THE SOFTWARE.
21+
// ------------------------------------------------------------------------------
22+
23+
package com.microsoft.graph.serializer;
24+
25+
import java.io.IOException;
26+
import java.util.HashMap;
27+
import java.util.Map;
28+
29+
import com.google.common.base.CaseFormat;
30+
import com.google.gson.Gson;
31+
import com.google.gson.TypeAdapter;
32+
import com.google.gson.TypeAdapterFactory;
33+
import com.google.gson.reflect.TypeToken;
34+
import com.google.gson.stream.JsonReader;
35+
import com.google.gson.stream.JsonToken;
36+
import com.google.gson.stream.JsonWriter;
37+
import com.microsoft.graph.logger.ILogger;
38+
39+
/**
40+
* Handles serialization/deserialization for special types (especially of
41+
* fields which are not caught by registering a type adapter).
42+
*/
43+
public final class FallBackTypeAdapter implements TypeAdapterFactory {
44+
45+
/**
46+
* The unexpected value constant
47+
*/
48+
private static final String NO_KNOWN_VALUE = "unexpectedValue";
49+
50+
/**
51+
* The logger instance
52+
*/
53+
private final ILogger logger;
54+
55+
/**
56+
* Serializes an instance of Void (which is always null).
57+
*/
58+
private static final TypeAdapter<Void> voidAdapter = new TypeAdapter<Void>() {
59+
60+
@Override
61+
public void write(JsonWriter out, Void value) throws IOException {
62+
out.nullValue();
63+
}
64+
65+
@Override
66+
public Void read(JsonReader in) throws IOException {
67+
return null;
68+
}
69+
70+
};
71+
72+
public FallBackTypeAdapter(ILogger logger) {
73+
this.logger = logger;
74+
}
75+
76+
@SuppressWarnings("unchecked")
77+
@Override
78+
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
79+
final Class<T> rawType = (Class<T>) type.getRawType();
80+
if (rawType.isEnum()) {
81+
return new EnumTypeAdapter<T>(rawType, logger);
82+
} else if (rawType == Void.class) {
83+
return (TypeAdapter<T>) voidAdapter;
84+
}
85+
else {
86+
return null;
87+
}
88+
}
89+
90+
private static final class EnumTypeAdapter<T> extends TypeAdapter<T> {
91+
92+
private final Map<String, T> enumValues;
93+
private final ILogger logger;
94+
95+
EnumTypeAdapter(Class<T> cls, ILogger logger) {
96+
super();
97+
this.logger = logger;
98+
final Map<String, T> enumValues = new HashMap<>();
99+
for (T constant : cls.getEnumConstants()) {
100+
enumValues.put(constant.toString(), constant);
101+
}
102+
this.enumValues = enumValues;
103+
}
104+
105+
@Override
106+
public void write(final JsonWriter out, final T value) throws IOException {
107+
if (value == null) {
108+
out.nullValue();
109+
} else {
110+
out.value(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, value.toString()));
111+
}
112+
}
113+
114+
@Override
115+
public T read(final JsonReader reader) throws IOException {
116+
if (reader.peek() == JsonToken.NULL) {
117+
reader.nextNull();
118+
return null;
119+
} else {
120+
String value = reader.nextString();
121+
T incoming = enumValues.get(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, value));
122+
if (incoming == null) {
123+
logger.logDebug(
124+
String.format(
125+
"The following value %s could not be recognized as a member of the enum",
126+
value)
127+
);
128+
return enumValues.get(NO_KNOWN_VALUE);
129+
}
130+
return incoming;
131+
}
132+
}
133+
}
134+
135+
}
136+

src/main/java/com/microsoft/graph/serializer/GsonFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ public Duration deserialize(final JsonElement json,
209209
}
210210
}
211211
};
212-
213212
return new GsonBuilder()
214213
.excludeFieldsWithoutExposeAnnotation()
215214
.registerTypeAdapter(Calendar.class, calendarJsonSerializer)
@@ -224,7 +223,7 @@ public Duration deserialize(final JsonElement json,
224223
.registerTypeAdapter(EnumSet.class, enumSetJsonDeserializer)
225224
.registerTypeAdapter(Duration.class, durationJsonSerializer)
226225
.registerTypeAdapter(Duration.class, durationJsonDeserializer)
227-
.registerTypeAdapterFactory(new FallBackEnumTypeAdapter())
226+
.registerTypeAdapterFactory(new FallBackTypeAdapter(logger))
228227
.create();
229228
}
230229
}

src/test/java/com/microsoft/graph/serializer/DefaultSeralizerTests.java renamed to src/test/java/com/microsoft/graph/serializer/DefaultSerializerTests.java

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

88
import com.google.gson.JsonElement;
99
import com.google.gson.JsonObject;
10+
import com.google.gson.annotations.Expose;
11+
import com.google.gson.annotations.SerializedName;
1012
import com.microsoft.graph.http.MockConnection;
1113
import com.microsoft.graph.logger.DefaultLogger;
1214
import com.microsoft.graph.models.extensions.Attachment;
@@ -17,7 +19,7 @@
1719
import com.microsoft.graph.models.generated.BaseRecurrenceRange;
1820
import com.microsoft.graph.models.generated.RecurrenceRangeType;
1921

20-
public class DefaultSeralizerTests {
22+
public class DefaultSerializerTests {
2123

2224
/**
2325
* Make sure that deserializing a Drive also returns members from BaseDrive
@@ -85,7 +87,7 @@ public void testResponseHeaders() throws Exception {
8587
assertEquals("value1", responseHeader.getAsJsonArray().get(0).getAsString());
8688
}
8789

88-
@Test
90+
@Test
8991
public void testDeserializeDerivedType() throws Exception {
9092
final DefaultSerializer serializer = new DefaultSerializer(new DefaultLogger());
9193
String source = "{\"@odata.context\": \"/attachments/$entity\",\"@odata.type\": \"#microsoft.graph.fileAttachment\",\"id\": \"AAMkAGQ0MjBmNWVkLTYxZjUtNDRmYi05Y2NiLTBlYjIwNzJjNmM1NgBGAAAAAAC6ff7latYeQqu_gLrhSAIhBwCF7iGjpaOmRqVwbZc-xXzwAAAAAAEMAACF7iGjpaOmRqVwbZc-xXzwAABQStA0AAABEgAQAFbGmeisbjtLnQdp7kC_9Fk=\",\"lastModifiedDateTime\": \"2018-01-23T21:50:22Z\",\"name\": \"Test Book.xlsx\",\"contentType\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\"size\": 8457,\"isInline\": false,\"contentId\": null,\"contentLocation\": null,\"contentBytes\": \"bytedata\"}";
@@ -99,4 +101,24 @@ public void testDeserializeDerivedType() throws Exception {
99101
assertNotNull(o);
100102
assertEquals("#microsoft.graph.fileAttachment", o. get("@odata.type").getAsString());
101103
}
104+
105+
@Test
106+
public void testSerializerCanSerializeVoid() {
107+
final DefaultSerializer serializer = new DefaultSerializer(new DefaultLogger());
108+
Test1 t = new Test1();
109+
String json = serializer.serializeObject(t);
110+
// this line will emit a warning from Java 9 about illegal access to the constructor of Void
111+
// if gson TypeAdapterFactory is not handling Void properly
112+
serializer.deserializeObject(json, Test1.class);
113+
}
114+
115+
public static final class Test1 {
116+
@SerializedName("x")
117+
@Expose
118+
int x = 1;
119+
120+
@SerializedName("y")
121+
@Expose
122+
Void y;
123+
}
102124
}

0 commit comments

Comments
 (0)