Skip to content

Commit 768eaa2

Browse files
authored
GraphQL serialization of java.util.Map #668 (#669)
1 parent 2cb4ae9 commit 768eaa2

File tree

3 files changed

+79
-18
lines changed

3 files changed

+79
-18
lines changed

src/main/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializer.java

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public static String getEntry(Object input) {
145145
/**
146146
* Serialize object to a string
147147
*
148-
* @param input can be any object or collection of objects.
148+
* @param input can be any object or collection/map of objects.
149149
* @param useObjectMapper if true, then use Jackson's ObjectMapper to convert from object to string,
150150
* otherwise use toString
151151
* @return serialized object
@@ -154,19 +154,16 @@ public static String getEntry(Object input) {
154154
public static String getEntry(Object input, boolean useObjectMapper) {
155155
if (input == null) {
156156
return null;
157-
}
158-
if (input instanceof Collection<?>) {
159-
StringJoiner joiner = new StringJoiner(", ", "[ ", " ]");
160-
for (Object collectionEntry : (Collection<?>) input) {
161-
joiner.add(getEntry(collectionEntry, useObjectMapper));
162-
}
163-
return joiner.toString();
164-
}
165-
if (useObjectMapper) {
157+
} else if (useObjectMapper) {
166158
return objectMapperWriteValueAsString(input);
167-
}
168-
if (input instanceof Enum<?>) {
169-
return input.toString();
159+
} else if (input instanceof Collection<?>) {
160+
return serializeCollection((Collection<?>) input, useObjectMapper);
161+
} else if (input instanceof Map<?, ?>) {
162+
return serializeMap((Map<?, ?>) input, useObjectMapper);
163+
} else if (input instanceof Map.Entry<?, ?>) {
164+
return serializeMapEntry((Map.Entry<?, ?>) input, useObjectMapper);
165+
} else if (input instanceof Enum<?>) {
166+
return serializeEnum((Enum<?>) input);
170167
} else if (input instanceof String) {
171168
return escapeJsonString(input.toString());
172169
} else if (input.getClass().getName().equals("scala.Some")) { // TODO: move to Scala Serializer
@@ -180,13 +177,29 @@ public static String getEntry(Object input, boolean useObjectMapper) {
180177
}
181178
}
182179

180+
public static String serializeCollection(Collection<?> input, boolean useObjectMapper) {
181+
StringJoiner joiner = new StringJoiner(", ", "[ ", " ]");
182+
for (Object entry : input) {
183+
joiner.add(getEntry(entry, useObjectMapper));
184+
}
185+
return joiner.toString();
186+
}
183187

184-
public static String objectMapperWriteValueAsString(Object input) {
185-
try {
186-
return OBJECT_MAPPER.writeValueAsString(input);
187-
} catch (JsonProcessingException e) {
188-
throw new UnableToBuildJsonQueryException(e);
188+
public static String serializeMap(Map<?, ?> input, boolean useObjectMapper) {
189+
StringJoiner joiner = new StringJoiner(", ", "{ ", " }");
190+
for (Map.Entry<?, ?> entry : input.entrySet()) {
191+
joiner.add(getEntry(entry, useObjectMapper));
189192
}
193+
return joiner.toString();
194+
}
195+
196+
public static String serializeMapEntry(Map.Entry<?, ?> input, boolean useObjectMapper) {
197+
// no need to quote String key
198+
return input.getKey() + ": " + getEntry(input.getValue(), useObjectMapper);
199+
}
200+
201+
public static String serializeEnum(Enum<?> input) {
202+
return input.toString();
190203
}
191204

192205
/**
@@ -231,4 +244,12 @@ public static String escapeJsonString(String stringValue) {
231244
return sb.toString();
232245
}
233246

247+
public static String objectMapperWriteValueAsString(Object input) {
248+
try {
249+
return OBJECT_MAPPER.writeValueAsString(input);
250+
} catch (JsonProcessingException e) {
251+
throw new UnableToBuildJsonQueryException(e);
252+
}
253+
}
254+
234255
}

src/test/java/com/kobylynskyi/graphql/codegen/model/graphql/GraphQLRequestSerializerTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.time.ZoneOffset;
2727
import java.time.ZonedDateTime;
2828
import java.util.Arrays;
29+
import java.util.HashMap;
30+
import java.util.Map;
2931
import java.util.function.Function;
3032
import java.util.stream.Stream;
3133

@@ -422,6 +424,7 @@ void serialize_collectionRequest_Null(String name, Function<GraphQLRequest, Stri
422424
.setContextId("something")
423425
.setIds(null)
424426
.setTranslated(false)
427+
.setEntries(null)
425428
.build();
426429
GraphQLRequest graphQLRequest = new GraphQLRequest(request,
427430
new EventResponseProjection()
@@ -433,6 +436,32 @@ void serialize_collectionRequest_Null(String name, Function<GraphQLRequest, Stri
433436
assertEquals(expectedQueryDecorator.apply(expectedQueryStr), serializedQuery);
434437
}
435438

439+
@ParameterizedTest(name = "{0}")
440+
@MethodSource("provideAllSerializers")
441+
void serialize_requestWithMap(String name, Function<GraphQLRequest, String> serializer,
442+
Function<String, String> expectedQueryDecorator) {
443+
Map<Object, Object> entries = new HashMap<>();
444+
entries.put("entryInt", 1);
445+
entries.put("entryString", "2");
446+
entries.put("entryFloat", 3.3);
447+
entries.put("entryNull", null);
448+
EventsByIdsQueryRequest request = new EventsByIdsQueryRequest.Builder()
449+
.setContextId("something")
450+
.setIds(null)
451+
.setTranslated(false)
452+
.setEntries(entries)
453+
.build();
454+
GraphQLRequest graphQLRequest = new GraphQLRequest(request,
455+
new EventResponseProjection()
456+
.id()
457+
);
458+
String serializedQuery = serializer.apply(graphQLRequest).replaceAll(" +", " ").trim();
459+
String expectedQueryStr = "query eventsByIds { " +
460+
"eventsByIds(contextId: \"something\", translated: false, entries: " +
461+
"{ entryNull: null, entryInt: 1, entryFloat: 3.3, entryString: \"2\" }){ id } }";
462+
assertEquals(expectedQueryDecorator.apply(expectedQueryStr), serializedQuery);
463+
}
464+
436465
@ParameterizedTest(name = "{0}")
437466
@MethodSource("provideAllSerializers")
438467
void serialize_AllInputsNull(String name, Function<GraphQLRequest, String> serializer,

src/test/java/com/kobylynskyi/graphql/codegen/model/graphql/data/EventsByIdsQueryRequest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public void setTranslated(Boolean translated) {
3737
this.input.put("translated", translated);
3838
}
3939

40+
public void setEntries(Map<Object, Object> entries) {
41+
this.input.put("entries", entries);
42+
}
43+
4044
@Override
4145
public GraphQLOperation getOperationType() {
4246
return OPERATION_TYPE;
@@ -72,6 +76,7 @@ public static class Builder {
7276
private String contextId;
7377
private Collection<String> ids;
7478
private Boolean translated;
79+
private Map<Object, Object> entries;
7580

7681
public Builder() {
7782
}
@@ -91,12 +96,18 @@ public Builder setTranslated(Boolean translated) {
9196
return this;
9297
}
9398

99+
public Builder setEntries(Map<Object, Object> entries) {
100+
this.entries = entries;
101+
return this;
102+
}
103+
94104

95105
public EventsByIdsQueryRequest build() {
96106
EventsByIdsQueryRequest obj = new EventsByIdsQueryRequest();
97107
obj.setContextId(contextId);
98108
obj.setIds(ids);
99109
obj.setTranslated(translated);
110+
obj.setEntries(entries);
100111
return obj;
101112
}
102113

0 commit comments

Comments
 (0)