Skip to content

Commit

Permalink
Add support for map in the runtime.
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeWharton committed Jun 14, 2016
1 parent 39827e9 commit 8f0167d
Show file tree
Hide file tree
Showing 24 changed files with 1,666 additions and 285 deletions.
4 changes: 2 additions & 2 deletions gen_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ cp src/test/proto-java.compact/com/squareup/wire/protos/alltypes/AllTypes.java \

cp src/test/proto-java.compact/com/squareup/wire/protos/alltypes/AllTypes.java \
../wire-gson-support/src/test/java/com/squareup/wire/protos/alltypes/AllTypes.java
cp src/test/proto-java/com/squareup/wire/protos/RepeatedAndPacked.java \
../wire-gson-support/src/test/java/com/squareup/wire/protos/RepeatedAndPacked.java
cp src/test/proto-java/com/squareup/wire/protos/RepeatedPackedAndMap.java \
../wire-gson-support/src/test/java/com/squareup/wire/protos/RepeatedPackedAndMap.java

rm -r src/test/proto-java.noOptions
rm -r src/test/proto-java.pruned
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.squareup</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
package com.squareup.wire;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -110,51 +111,63 @@ private void emitUint64(Long value, JsonWriter out) throws IOException {
return null;
}

TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
B builder = messageAdapter.newBuilder();
in.beginObject();

while (in.peek() == JsonToken.NAME) {
in.beginObject();
while (in.peek() != JsonToken.END_OBJECT) {
String name = in.nextName();

FieldBinding<M, B> fieldBinding = fieldBindings.get(name);
if (fieldBinding != null) {
Object value = parseValue(fieldBinding.label, singleType(fieldBinding), parse(in));
if (fieldBinding == null) {
in.skipValue();
} else {
JsonElement element = elementAdapter.read(in);
Object value = parseValue(fieldBinding, element);
fieldBinding.set(builder, value);
continue;
}

in.skipValue();
}

in.endObject();
return builder.build();
}

private JsonElement parse(JsonReader in) {
return gson.fromJson(in, JsonElement.class);
}

private Object parseValue(Label label, Type valueType, JsonElement valueElement) {
if (label.isRepeated()) {
if (valueElement.isJsonNull()) {
private Object parseValue(FieldBinding<?, ?> fieldBinding, JsonElement element) {
if (fieldBinding.label.isRepeated()) {
if (element.isJsonNull()) {
return Collections.emptyList();
}

List<Object> valueList = new ArrayList<>();
for (JsonElement element : valueElement.getAsJsonArray()) {
valueList.add(readJson(valueType, element));
Class<?> itemType = fieldBinding.singleAdapter().javaType;

JsonArray array = element.getAsJsonArray();
List<Object> result = new ArrayList<>(array.size());
for (JsonElement item : array) {
result.add(gson.fromJson(item, itemType));
}
return valueList;
} else {
return readJson(valueType, valueElement);
return result;
}
}

private Object readJson(Type valueType, JsonElement element) {
return gson.fromJson(element, valueType);
}
if (fieldBinding.isMap()) {
if (element.isJsonNull()) {
return Collections.emptyMap();
}

Class<?> keyType = fieldBinding.keyAdapter().javaType;
Class<?> valueType = fieldBinding.singleAdapter().javaType;

JsonObject object = element.getAsJsonObject();
// TODO Pre-size this collection when https://github.com/google/gson/pull/872 is released.
Map<Object, Object> result = new LinkedHashMap<>();
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
Object key = gson.fromJson(entry.getKey(), keyType);
Object value = gson.fromJson(entry.getValue(), valueType);
result.put(key, value);
}
return result;
}

private Type singleType(FieldBinding<M, B> tagBinding) {
return tagBinding.singleAdapter().javaType;
Class<?> elementType = fieldBinding.singleAdapter().javaType;
return gson.fromJson(element, elementType);
}
}
56 changes: 35 additions & 21 deletions wire-gson-support/src/test/java/com/squareup/wire/GsonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.squareup.wire.protos.RepeatedAndPacked;
import com.squareup.wire.protos.RepeatedPackedAndMap;
import com.squareup.wire.protos.alltypes.AllTypes;
import java.util.Arrays;
import java.util.List;
import okio.ByteString;
import org.junit.Test;

import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;

public class GsonTest {
Expand Down Expand Up @@ -92,6 +93,10 @@ public class GsonTest {
+ "\"pack_float\":[122.0,122.0],"
+ "\"pack_double\":[123.0,123.0],"
+ "\"pack_nested_enum\":[\"A\",\"A\"],"
+ "\"map_int32_int32\":{\"1\":2},"
+ "\"map_string_string\":{\"key\":\"value\"},"
+ "\"map_string_message\":{\"message\":{\"a\":1}},"
+ "\"map_string_enum\":{\"enum\":\"A\"},"
+ "\"ext_opt_int32\":2147483647,"
+ "\"ext_opt_int64\":-4611686018427387726,"
+ "\"ext_opt_uint64\":13835058055282163890,"
Expand Down Expand Up @@ -131,7 +136,11 @@ public class GsonTest {
+ "\"ext_pack_bool\":[true,true],"
+ "\"ext_pack_float\":[1234500.0,1234500.0],"
+ "\"ext_pack_double\":[1.2345E67,1.2345E67],"
+ "\"ext_pack_nested_enum\":[\"A\",\"A\"]}";
+ "\"ext_pack_nested_enum\":[\"A\",\"A\"],"
+ "\"ext_map_int32_int32\":{\"1\":2},"
+ "\"ext_map_string_string\":{\"key\":\"value\"},"
+ "\"ext_map_string_message\":{\"message\":{\"a\":1}},"
+ "\"ext_map_string_enum\":{\"enum\":\"A\"}}";

// Return a two-element list with a given repeated value
@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -208,6 +217,10 @@ private static AllTypes.Builder createBuilder() {
.pack_float(list(122.0F))
.pack_double(list(123.0))
.pack_nested_enum(list(AllTypes.NestedEnum.A))
.map_int32_int32(singletonMap(1, 2))
.map_string_string(singletonMap("key", "value"))
.map_string_message(singletonMap("message", new AllTypes.NestedMessage(1)))
.map_string_enum(singletonMap("enum", AllTypes.NestedEnum.A))
.ext_opt_int32(Integer.MAX_VALUE)
.ext_opt_int64(Long.MIN_VALUE / 2 + 178)
.ext_opt_uint64(Long.MIN_VALUE / 2 + 178)
Expand All @@ -231,34 +244,33 @@ private static AllTypes.Builder createBuilder() {
.ext_pack_bool(list(true))
.ext_pack_float(list(1.2345e6F))
.ext_pack_double(list(1.2345e67))
.ext_pack_nested_enum(list(AllTypes.NestedEnum.A));

}

private Gson createGson() {
return new GsonBuilder()
.registerTypeAdapterFactory(new WireTypeAdapterFactory())
.disableHtmlEscaping()
.create();
.ext_pack_nested_enum(list(AllTypes.NestedEnum.A))
.ext_map_int32_int32(singletonMap(1, 2))
.ext_map_string_string(singletonMap("key", "value"))
.ext_map_string_message(singletonMap("message", new AllTypes.NestedMessage(1)))
.ext_map_string_enum(singletonMap("enum", AllTypes.NestedEnum.A));
}

@Test
public void testGson() {
Gson gson = createGson();
private final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new WireTypeAdapterFactory())
.disableHtmlEscaping()
.create();

@Test public void serializationOfAllTypes() {
AllTypes allTypes = createBuilder().build();
String json = gson.toJson(allTypes);
assertThat(json).isEqualTo(JSON);
}

AllTypes parsed = gson.fromJson(json, AllTypes.class);
@Test public void deserializationOfAllTypes() {
AllTypes allTypes = createBuilder().build();
AllTypes parsed = gson.fromJson(JSON, AllTypes.class);
assertThat(parsed).isEqualTo(allTypes);
assertThat(parsed.toString()).isEqualTo(allTypes.toString());
assertThat(gson.toJson(parsed)).isEqualTo(gson.toJson(allTypes));
}

@Test public void testGsonOmitsUnknownFields() {
Gson gson = createGson();

@Test public void omitsUnknownFields() {
AllTypes.Builder builder = createBuilder();
builder.addUnknownField(9000, FieldEncoding.FIXED32, 9000);
builder.addUnknownField(9001, FieldEncoding.FIXED64, 9001L);
Expand All @@ -271,10 +283,12 @@ public void testGson() {
assertThat(json).isEqualTo(JSON);
}

@Test public void testNullRepeatedField() {
Gson gson = createGson();
RepeatedAndPacked parsed = gson.fromJson("{rep_int32=null,pack_int32=null}", RepeatedAndPacked.class);
@Test public void nullRepeatedField() {
RepeatedPackedAndMap parsed =
gson.fromJson("{rep_int32=null,pack_int32=null,map_int32_int32=null}",
RepeatedPackedAndMap.class);
assertThat(parsed.rep_int32).isEmpty();
assertThat(parsed.pack_int32).isEmpty();
assertThat(parsed.map_int32_int32).isEmpty();
}
}
Loading

0 comments on commit 8f0167d

Please sign in to comment.