Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ public InputFieldJsonWriter(JsonWriter jsonWriter, ScalarTypeAdapters scalarType
writeBoolean(fieldName, ((CustomTypeValue.GraphQLBoolean) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLNumber) {
writeNumber(fieldName, ((CustomTypeValue.GraphQLNumber) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLJsonString) {
writeString(fieldName, ((CustomTypeValue.GraphQLJsonString) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLJson) {
writeMap(fieldName, ((CustomTypeValue.GraphQLJson) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLJsonObject
|| customTypeValue instanceof CustomTypeValue.GraphQLJsonList) {
jsonWriter.name(fieldName);
writeToJson(value, jsonWriter);
} else {
throw new IllegalArgumentException("Unsupported custom value type: " + customTypeValue);
}
Expand Down Expand Up @@ -211,10 +211,9 @@ private static final class JsonListItemWriter implements ListItemWriter {
writeBoolean(((CustomTypeValue.GraphQLBoolean) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLNumber) {
writeNumber(((CustomTypeValue.GraphQLNumber) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLJsonString) {
writeString(((CustomTypeValue.GraphQLJsonString) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLJson) {
writeMap(((CustomTypeValue.GraphQLJson) customTypeValue).value);
} else if (customTypeValue instanceof CustomTypeValue.GraphQLJsonObject
|| customTypeValue instanceof CustomTypeValue.GraphQLJsonList) {
writeToJson(value, jsonWriter);
} else {
throw new IllegalArgumentException("Unsupported custom value type: " + customTypeValue);
}
Expand All @@ -241,4 +240,4 @@ private static final class JsonListItemWriter implements ListItemWriter {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ public interface CustomTypeAdapter<T> {
T decode(@NotNull CustomTypeValue value);

/**
* Serializes the custom scalar type to the corresponding string value. Usually used in serializing variables or input
* Serializes the custom scalar type to the corresponding {@link CustomTypeValue} value. Usually used in serializing variables or input
* values.
*
* @param value the custom scalar type to serialize
* @return serialized string value
* @return serialized value
*/
@NotNull CustomTypeValue encode(@NotNull T value);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.apollographql.apollo.response;

import com.apollographql.apollo.internal.json.Utils;

import java.util.List;
import java.util.Map;

Expand All @@ -15,13 +13,12 @@
public abstract class CustomTypeValue<T> {
public final T value;

@SuppressWarnings("unchecked")
public static CustomTypeValue fromRawValue(Object value) {
if (value instanceof Map || value instanceof List) {
try {
return new GraphQLJsonString(Utils.toJsonString(value));
} catch (Exception e) {
throw new RuntimeException(e);
}
if (value instanceof Map) {
return new GraphQLJsonObject((Map<String, Object>) value);
} else if (value instanceof List) {
return new GraphQLJsonList((List<Object>) value);
} else if (value instanceof Boolean) {
return new GraphQLBoolean((Boolean) value);
} else if (value instanceof Number) {
Expand Down Expand Up @@ -63,19 +60,19 @@ public GraphQLNumber(Number value) {
}

/**
* Represents a {@code JsonString} value
* Represents a JSON object value
*/
public static class GraphQLJsonString extends CustomTypeValue<String> {
public GraphQLJsonString(String value) {
public static class GraphQLJsonObject extends CustomTypeValue<Map<String, Object>> {
public GraphQLJsonObject(Map<String, Object> value) {
super(value);
}
}

/**
* Represents a JSON object value, will serialized as an regular json object
* Represents a JSON list value
*/
public static class GraphQLJson extends CustomTypeValue<Map<String, Object>> {
public GraphQLJson(Map<String, Object> value) {
public static class GraphQLJsonList extends CustomTypeValue<List<Object>> {
public GraphQLJsonList(List<Object> value) {
super(value);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.jetbrains.annotations.NotNull;
Expand All @@ -18,7 +19,7 @@ public final class ScalarTypeAdapters {
public ScalarTypeAdapters(@NotNull Map<ScalarType, CustomTypeAdapter> customAdapters) {
Map<ScalarType, CustomTypeAdapter> nonNullcustomAdapters = checkNotNull(customAdapters, "customAdapters == null");
this.customAdapters = new HashMap<>();
for (Map.Entry<ScalarType, CustomTypeAdapter> entry:nonNullcustomAdapters.entrySet()) {
for (Map.Entry<ScalarType, CustomTypeAdapter> entry : nonNullcustomAdapters.entrySet()) {
this.customAdapters.put(entry.getKey().typeName(), entry.getValue());
}
}
Expand Down Expand Up @@ -53,7 +54,7 @@ private static Map<Class, CustomTypeAdapter> defaultAdapters() {
} else if (value instanceof CustomTypeValue.GraphQLString) {
return Boolean.parseBoolean(((CustomTypeValue.GraphQLString) value).value);
} else {
throw new IllegalArgumentException("Can't map: " + value + " to Boolean");
throw new IllegalArgumentException("Can't decode: " + value + " into Boolean");
}
}
});
Expand All @@ -64,7 +65,7 @@ private static Map<Class, CustomTypeAdapter> defaultAdapters() {
} else if (value instanceof CustomTypeValue.GraphQLString) {
return Integer.parseInt(((CustomTypeValue.GraphQLString) value).value);
} else {
throw new IllegalArgumentException("Can't map: " + value + " to Integer");
throw new IllegalArgumentException("Can't decode: " + value + " into Integer");
}
}
});
Expand All @@ -75,7 +76,7 @@ private static Map<Class, CustomTypeAdapter> defaultAdapters() {
} else if (value instanceof CustomTypeValue.GraphQLString) {
return Long.parseLong(((CustomTypeValue.GraphQLString) value).value);
} else {
throw new IllegalArgumentException("Can't map: " + value + " to Long");
throw new IllegalArgumentException("Can't decode: " + value + " into Long");
}
}
});
Expand All @@ -86,7 +87,7 @@ private static Map<Class, CustomTypeAdapter> defaultAdapters() {
} else if (value instanceof CustomTypeValue.GraphQLString) {
return Float.parseFloat(((CustomTypeValue.GraphQLString) value).value);
} else {
throw new IllegalArgumentException("Can't map: " + value + " to Float");
throw new IllegalArgumentException("Can't decode: " + value + " into Float");
}
}
});
Expand All @@ -97,7 +98,7 @@ private static Map<Class, CustomTypeAdapter> defaultAdapters() {
} else if (value instanceof CustomTypeValue.GraphQLString) {
return Double.parseDouble(((CustomTypeValue.GraphQLString) value).value);
} else {
throw new IllegalArgumentException("Can't map: " + value + " to Double");
throw new IllegalArgumentException("Can't decode: " + value + " into Double");
}
}
});
Expand All @@ -117,6 +118,24 @@ public CustomTypeValue encode(@NotNull FileUpload value) {
return value.value;
}
});
adapters.put(Map.class, new DefaultCustomTypeAdapter<Map>() {
@NotNull @Override public Map decode(@NotNull CustomTypeValue value) {
if (value instanceof CustomTypeValue.GraphQLJsonObject) {
return ((CustomTypeValue.GraphQLJsonObject) value).value;
} else {
throw new IllegalArgumentException("Can't decode: " + value + " into Map");
}
}
});
adapters.put(List.class, new DefaultCustomTypeAdapter<List>() {
@NotNull @Override public List decode(@NotNull CustomTypeValue value) {
if (value instanceof CustomTypeValue.GraphQLJsonList) {
return ((CustomTypeValue.GraphQLJsonList) value).value;
} else {
throw new IllegalArgumentException("Can't decode: " + value + " into List");
}
}
});
return adapters;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -147,38 +148,54 @@ public void writeCustomString() throws IOException {
}

@Test
public void writeCustomJsonString() throws IOException {
Map<ScalarType, CustomTypeAdapter> customTypeAdapters = new HashMap<>();
customTypeAdapters.put(new MockCustomScalarType(CustomTypeValue.GraphQLJsonString.class), new MockCustomTypeAdapter() {
@NotNull @Override public CustomTypeValue encode(@NotNull Object value) {
return new CustomTypeValue.GraphQLJsonString((String) value);
}
});
inputFieldJsonWriter = new InputFieldJsonWriter(jsonWriter, new ScalarTypeAdapters(customTypeAdapters));
inputFieldJsonWriter.writeCustom("someField", new MockCustomScalarType(CustomTypeValue.GraphQLJsonString.class), "{\"someField\": \"someValue\"}");
inputFieldJsonWriter.writeCustom("someNullField", new MockCustomScalarType(CustomTypeValue.GraphQLJsonString.class), null);
assertThat(jsonBuffer.readUtf8()).isEqualTo("{\"someField\":\"{\\\"someField\\\": \\\"someValue\\\"}\",\"someNullField\":null");
public void writeCustomJsonObject() throws IOException {
final Map<String, Object> value = new UnmodifiableMapBuilder<String, Object>()
.put("stringField", "string")
.put("booleanField", true)
.put("numberField", new BigDecimal(100))
.put("listField", Arrays.asList(
"string",
true,
new BigDecimal(100),
new UnmodifiableMapBuilder<String, Object>()
.put("stringField", "string")
.put("numberField", new BigDecimal(100))
.put("booleanField", true)
.put("listField", Arrays.asList(1, 2, 3))
.build()
)
)
.put("objectField", new UnmodifiableMapBuilder<String, Object>()
.put("stringField", "string")
.put("numberField", new BigDecimal(100))
.put("booleanField", true)
.put("listField", Arrays.asList(1, 2, 3))
.build()
)
.build();

inputFieldJsonWriter.writeCustom("someField", new MockCustomScalarType(Map.class), value);
inputFieldJsonWriter.writeCustom("someNullField", new MockCustomScalarType(Map.class), null);
assertThat(jsonBuffer.readUtf8()).isEqualTo("{\"someField\":{\"objectField\":{\"numberField\":100,\"booleanField\":true,\"listField\":[1,2,3],\"stringField\":\"string\"},\"numberField\":100,\"booleanField\":true,\"listField\":[\"string\",true,100,{\"numberField\":100,\"booleanField\":true,\"listField\":[1,2,3],\"stringField\":\"string\"}],\"stringField\":\"string\"},\"someNullField\":null");
}

@Test
public void writeCustomJson() throws IOException {
Map<ScalarType, CustomTypeAdapter> customTypeAdapters = new HashMap<>();
customTypeAdapters.put(new MockCustomScalarType(CustomTypeValue.GraphQLJson.class), new MockCustomTypeAdapter() {
@NotNull @Override public CustomTypeValue encode(@NotNull Object value) {
return new CustomTypeValue.GraphQLJson((Map<String, Object>) value);
}
});
inputFieldJsonWriter = new InputFieldJsonWriter(jsonWriter, new ScalarTypeAdapters(customTypeAdapters));

Map<String, Object> objectMap = new LinkedHashMap<>();
objectMap.put("booleanField", true);
objectMap.put("stringField", "someValue");
objectMap.put("numberField", 100);
objectMap.put("objectField", new UnmodifiableMapBuilder().put("someField", "someValue").build());

inputFieldJsonWriter.writeCustom("someField", new MockCustomScalarType(CustomTypeValue.GraphQLJson.class), objectMap);
inputFieldJsonWriter.writeCustom("someNullField", new MockCustomScalarType(CustomTypeValue.GraphQLJson.class), null);
assertThat(jsonBuffer.readUtf8()).isEqualTo("{\"someField\":{\"booleanField\":true,\"stringField\":\"someValue\",\"numberField\":100,\"objectField\":{\"someField\":\"someValue\"}},\"someNullField\":null");
public void writeCustomList() throws IOException {
final List<Object> value = Arrays.asList(
"string",
true,
new BigDecimal(100),
new UnmodifiableMapBuilder<String, Object>()
.put("stringField", "string")
.put("numberField", new BigDecimal(100))
.put("booleanField", true)
.put("listField", Arrays.asList(1, 2, 3))
.build()
);

inputFieldJsonWriter.writeCustom("someField", new MockCustomScalarType(List.class), value);
inputFieldJsonWriter.writeCustom("someNullField", new MockCustomScalarType(List.class), null);
assertThat(jsonBuffer.readUtf8()).isEqualTo("{\"someField\":[\"string\",true,100,{\"numberField\":100,\"booleanField\":true,\"listField\":[1,2,3],\"stringField\":\"string\"}],\"someNullField\":null");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,21 @@ public class ResponseReaderTest {
}
}

@Test public void readCustomObjectMap() throws Exception {
ResponseField successField = ResponseField.forCustomType("successFieldResponseName", "successFieldName", null,
false, OBJECT_CUSTOM_TYPE, NO_CONDITIONS);
@Test public void readCustomObjectMap() {
final ScalarType mapScalarType = new ScalarType() {
@Override public String typeName() {
return Map.class.getName();
}

@Override public Class javaType() {
return Map.class;
}
};

final ResponseField successField = ResponseField.forCustomType("successFieldResponseName", "successFieldName", null,
false, mapScalarType, NO_CONDITIONS);

Map<String, Object> objectMap = new HashMap<>();
final Map<String, Object> objectMap = new HashMap<>();
objectMap.put("string", "string");
objectMap.put("boolean", true);
objectMap.put("double", 1.99D);
Expand All @@ -214,50 +224,41 @@ public class ResponseReaderTest {
objectMap.put("object", new HashMap<>(objectMap));
objectMap.put("objectList", asList(new HashMap<>(objectMap), new HashMap<>(objectMap)));

Map<String, Object> recordSet = new HashMap<>();
final Map<String, Object> recordSet = new HashMap<>();
recordSet.put("successFieldResponseName", objectMap);
recordSet.put("successFieldName", objectMap);

RealResponseReader<Map<String, Object>> responseReader = responseReader(recordSet);
assertThat(responseReader.readCustomType((ResponseField.CustomTypeField) successField))
.isEqualTo("{\"string\":\"string\",\"double\":1.99,\"intList\":[8,9,10],\"doubleList\":[1.99,2.99]," +
"\"float\":2.99,\"longList\":[5,7],\"long\":3,\"int\":4,\"objectList\":[{\"string\":\"string\"," +
"\"double\":1.99,\"intList\":[8,9,10],\"doubleList\":[1.99,2.99],\"float\":2.99,\"longList\":[5,7]," +
"\"long\":3,\"int\":4,\"boolean\":true,\"stringList\":[\"string1\",\"string2\"]," +
"\"floatList\":[3.99,4.99,5.99],\"booleanList\":[\"true\",\"false\"],\"object\":{\"string\":\"string\"," +
"\"double\":1.99,\"intList\":[8,9,10],\"doubleList\":[1.99,2.99],\"float\":2.99,\"longList\":[5,7]," +
"\"long\":3,\"int\":4,\"boolean\":true,\"stringList\":[\"string1\",\"string2\"]," +
"\"floatList\":[3.99,4.99,5.99],\"booleanList\":[\"true\",\"false\"]}},{\"string\":\"string\"," +
"\"double\":1.99,\"intList\":[8,9,10],\"doubleList\":[1.99,2.99],\"float\":2.99,\"longList\":[5,7]," +
"\"long\":3,\"int\":4,\"boolean\":true,\"stringList\":[\"string1\",\"string2\"]," +
"\"floatList\":[3.99,4.99,5.99],\"booleanList\":[\"true\",\"false\"],\"object\":{\"string\":\"string\"," +
"\"double\":1.99,\"intList\":[8,9,10],\"doubleList\":[1.99,2.99],\"float\":2.99,\"longList\":[5,7]," +
"\"long\":3,\"int\":4,\"boolean\":true,\"stringList\":[\"string1\",\"string2\"]," +
"\"floatList\":[3.99,4.99,5.99],\"booleanList\":[\"true\",\"false\"]}}],\"boolean\":true," +
"\"stringList\":[\"string1\",\"string2\"],\"floatList\":[3.99,4.99,5.99]," +
"\"booleanList\":[\"true\",\"false\"],\"object\":{\"string\":\"string\",\"double\":1.99," +
"\"intList\":[8,9,10],\"doubleList\":[1.99,2.99],\"float\":2.99,\"longList\":[5,7],\"long\":3,\"int\":4," +
"\"boolean\":true,\"stringList\":[\"string1\",\"string2\"],\"floatList\":[3.99,4.99,5.99]," +
"\"booleanList\":[\"true\",\"false\"]}}");
final RealResponseReader<Map<String, Object>> responseReader = responseReader(recordSet);
assertThat((Map<?, ?>) responseReader.readCustomType((ResponseField.CustomTypeField) successField))
.containsExactlyEntriesIn(objectMap);
}

@Test public void readCustomObjectList() throws Exception {
ResponseField successField = ResponseField.forCustomType("successFieldResponseName", "successFieldName", null,
false, OBJECT_CUSTOM_TYPE, NO_CONDITIONS);
@Test public void readCustomObjectList() {
final ScalarType listScalarType = new ScalarType() {
@Override public String typeName() {
return List.class.getName();
}

Map<String, Object> objectMap = new HashMap<>();
@Override public Class javaType() {
return List.class;
}
};
final ResponseField successField = ResponseField.forCustomType("successFieldResponseName", "successFieldName", null,
false, listScalarType, NO_CONDITIONS);

final Map<String, Object> objectMap = new HashMap<>();
objectMap.put("string", "string");
objectMap.put("boolean", true);

List<?> objectList = asList(objectMap, objectMap);
final List<?> objectList = asList(objectMap, objectMap);

Map<String, Object> recordSet = new HashMap<>();
final Map<String, Object> recordSet = new HashMap<>();
recordSet.put("successFieldResponseName", objectList);
recordSet.put("successFieldName", objectList);

RealResponseReader<Map<String, Object>> responseReader = responseReader(recordSet);
assertThat(responseReader.readCustomType((ResponseField.CustomTypeField) successField))
.isEqualTo("[{\"boolean\":true,\"string\":\"string\"},{\"boolean\":true,\"string\":\"string\"}]");
final RealResponseReader<Map<String, Object>> responseReader = responseReader(recordSet);
assertThat((List<?>) responseReader.readCustomType((ResponseField.CustomTypeField) successField))
.containsExactlyElementsIn(objectList);
}

@Test public void readCustomWithDecodedNullValue() throws Exception {
Expand Down
Loading