Java protobuf uses lower camel for all field names. When using reflection to find the generic type of repeated fields, can't use the user specified formats for field name conversion. (#1119)

This commit is contained in:
Ori Schwartz 2017-09-18 02:46:52 -04:00 committed by inder123
parent 558c13918e
commit f0aa1118e9
3 changed files with 50 additions and 9 deletions

View File

@ -19,7 +19,6 @@ package com.google.gson.protobuf;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import com.google.common.collect.MapMaker;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
@ -94,7 +93,8 @@ public class ProtoTypeAdapter
private final Set<Extension<FieldOptions, String>> serializedNameExtensions;
private final Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions;
private EnumSerialization enumSerialization;
private Converter<String, String> fieldNameSerializationFormat;
private CaseFormat protoFormat;
private CaseFormat jsonFormat;
private Builder(EnumSerialization enumSerialization, CaseFormat fromFieldNameFormat,
CaseFormat toFieldNameFormat) {
@ -126,7 +126,8 @@ public class ProtoTypeAdapter
*/
public Builder setFieldNameSerializationFormat(CaseFormat fromFieldNameFormat,
CaseFormat toFieldNameFormat) {
fieldNameSerializationFormat = fromFieldNameFormat.converterTo(toFieldNameFormat);
this.protoFormat = fromFieldNameFormat;
this.jsonFormat = toFieldNameFormat;
return this;
}
@ -174,7 +175,7 @@ public class ProtoTypeAdapter
}
public ProtoTypeAdapter build() {
return new ProtoTypeAdapter(enumSerialization, fieldNameSerializationFormat,
return new ProtoTypeAdapter(enumSerialization, protoFormat, jsonFormat,
serializedNameExtensions, serializedEnumValueExtensions);
}
}
@ -195,16 +196,19 @@ public class ProtoTypeAdapter
new MapMaker().makeMap();
private final EnumSerialization enumSerialization;
private final Converter<String, String> fieldNameSerializationFormat;
private final CaseFormat protoFormat;
private final CaseFormat jsonFormat;
private final Set<Extension<FieldOptions, String>> serializedNameExtensions;
private final Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions;
private ProtoTypeAdapter(EnumSerialization enumSerialization,
Converter<String, String> fieldNameSerializationFormat,
CaseFormat protoFormat,
CaseFormat jsonFormat,
Set<Extension<FieldOptions, String>> serializedNameExtensions,
Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions) {
this.enumSerialization = enumSerialization;
this.fieldNameSerializationFormat = fieldNameSerializationFormat;
this.protoFormat = protoFormat;
this.jsonFormat = jsonFormat;
this.serializedNameExtensions = serializedNameExtensions;
this.serializedEnumValueExtensions = serializedEnumValueExtensions;
}
@ -284,8 +288,9 @@ public class ProtoTypeAdapter
protoBuilder.setField(fieldDescriptor, fieldValue);
} else if (fieldDescriptor.isRepeated()) {
// If the type is an array, then we have to grab the type from the class.
// protobuf java field names are always lower camel case
String protoArrayFieldName =
fieldNameSerializationFormat.convert(fieldDescriptor.getName()) + "_";
protoFormat.to(CaseFormat.LOWER_CAMEL, fieldDescriptor.getName()) + "_";
Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName);
Type protoArrayFieldType = protoArrayField.getGenericType();
fieldValue = context.deserialize(jsonElement, protoArrayFieldType);
@ -325,7 +330,7 @@ public class ProtoTypeAdapter
return options.getExtension(extension);
}
}
return fieldNameSerializationFormat.convert(defaultName);
return protoFormat.to(jsonFormat, defaultName);
}
/**

View File

@ -24,6 +24,11 @@ message SimpleProto {
optional int32 count = 2;
}
message ProtoWithDifferentCaseFormat {
repeated string name_that_tests_case_format = 1;
optional string another_field = 2;
}
message ProtoWithRepeatedFields {
repeated int64 numbers = 1;
repeated SimpleProto simples = 2;

View File

@ -15,10 +15,13 @@
*/
package com.google.gson.protobuf.functional;
import com.google.common.base.CaseFormat;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.protobuf.ProtoTypeAdapter;
import com.google.gson.protobuf.ProtoTypeAdapter.EnumSerialization;
import com.google.gson.protobuf.generated.Bag.ProtoWithDifferentCaseFormat;
import com.google.gson.protobuf.generated.Bag.ProtoWithRepeatedFields;
import com.google.gson.protobuf.generated.Bag.SimpleProto;
import com.google.protobuf.GeneratedMessage;
@ -32,6 +35,7 @@ import junit.framework.TestCase;
*/
public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
private Gson gson;
private Gson upperCamelGson;
@Override
protected void setUp() throws Exception {
@ -43,6 +47,14 @@ public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
.setEnumSerialization(EnumSerialization.NUMBER)
.build())
.create();
upperCamelGson =
new GsonBuilder()
.registerTypeHierarchyAdapter(
GeneratedMessage.class, ProtoTypeAdapter.newBuilder()
.setFieldNameSerializationFormat(
CaseFormat.LOWER_UNDERSCORE, CaseFormat.UPPER_CAMEL)
.build())
.create();
}
public void testSerializeRepeatedFields() {
@ -67,4 +79,23 @@ public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
assertEquals("bar", proto.getSimples(0).getMsg());
assertEquals(7, proto.getSimples(1).getCount());
}
public void testSerializeDifferentCaseFormat() {
final ProtoWithDifferentCaseFormat proto =
ProtoWithDifferentCaseFormat.newBuilder()
.setAnotherField("foo")
.addNameThatTestsCaseFormat("bar")
.build();
final JsonObject json = upperCamelGson.toJsonTree(proto).getAsJsonObject();
assertEquals("foo", json.get("AnotherField").getAsString());
assertEquals("bar", json.get("NameThatTestsCaseFormat").getAsJsonArray().get(0).getAsString());
}
public void testDeserializeDifferentCaseFormat() {
final String json = "{NameThatTestsCaseFormat:['bar'],AnotherField:'foo'}";
ProtoWithDifferentCaseFormat proto =
upperCamelGson.fromJson(json, ProtoWithDifferentCaseFormat.class);
assertEquals("foo", proto.getAnotherField());
assertEquals("bar", proto.getNameThatTestsCaseFormat(0));
}
}