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:
parent
558c13918e
commit
f0aa1118e9
|
@ -19,7 +19,6 @@ package com.google.gson.protobuf;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
import com.google.common.base.Converter;
|
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
@ -94,7 +93,8 @@ public class ProtoTypeAdapter
|
||||||
private final Set<Extension<FieldOptions, String>> serializedNameExtensions;
|
private final Set<Extension<FieldOptions, String>> serializedNameExtensions;
|
||||||
private final Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions;
|
private final Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions;
|
||||||
private EnumSerialization enumSerialization;
|
private EnumSerialization enumSerialization;
|
||||||
private Converter<String, String> fieldNameSerializationFormat;
|
private CaseFormat protoFormat;
|
||||||
|
private CaseFormat jsonFormat;
|
||||||
|
|
||||||
private Builder(EnumSerialization enumSerialization, CaseFormat fromFieldNameFormat,
|
private Builder(EnumSerialization enumSerialization, CaseFormat fromFieldNameFormat,
|
||||||
CaseFormat toFieldNameFormat) {
|
CaseFormat toFieldNameFormat) {
|
||||||
|
@ -126,7 +126,8 @@ public class ProtoTypeAdapter
|
||||||
*/
|
*/
|
||||||
public Builder setFieldNameSerializationFormat(CaseFormat fromFieldNameFormat,
|
public Builder setFieldNameSerializationFormat(CaseFormat fromFieldNameFormat,
|
||||||
CaseFormat toFieldNameFormat) {
|
CaseFormat toFieldNameFormat) {
|
||||||
fieldNameSerializationFormat = fromFieldNameFormat.converterTo(toFieldNameFormat);
|
this.protoFormat = fromFieldNameFormat;
|
||||||
|
this.jsonFormat = toFieldNameFormat;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +175,7 @@ public class ProtoTypeAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProtoTypeAdapter build() {
|
public ProtoTypeAdapter build() {
|
||||||
return new ProtoTypeAdapter(enumSerialization, fieldNameSerializationFormat,
|
return new ProtoTypeAdapter(enumSerialization, protoFormat, jsonFormat,
|
||||||
serializedNameExtensions, serializedEnumValueExtensions);
|
serializedNameExtensions, serializedEnumValueExtensions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,16 +196,19 @@ public class ProtoTypeAdapter
|
||||||
new MapMaker().makeMap();
|
new MapMaker().makeMap();
|
||||||
|
|
||||||
private final EnumSerialization enumSerialization;
|
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<FieldOptions, String>> serializedNameExtensions;
|
||||||
private final Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions;
|
private final Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions;
|
||||||
|
|
||||||
private ProtoTypeAdapter(EnumSerialization enumSerialization,
|
private ProtoTypeAdapter(EnumSerialization enumSerialization,
|
||||||
Converter<String, String> fieldNameSerializationFormat,
|
CaseFormat protoFormat,
|
||||||
|
CaseFormat jsonFormat,
|
||||||
Set<Extension<FieldOptions, String>> serializedNameExtensions,
|
Set<Extension<FieldOptions, String>> serializedNameExtensions,
|
||||||
Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions) {
|
Set<Extension<EnumValueOptions, String>> serializedEnumValueExtensions) {
|
||||||
this.enumSerialization = enumSerialization;
|
this.enumSerialization = enumSerialization;
|
||||||
this.fieldNameSerializationFormat = fieldNameSerializationFormat;
|
this.protoFormat = protoFormat;
|
||||||
|
this.jsonFormat = jsonFormat;
|
||||||
this.serializedNameExtensions = serializedNameExtensions;
|
this.serializedNameExtensions = serializedNameExtensions;
|
||||||
this.serializedEnumValueExtensions = serializedEnumValueExtensions;
|
this.serializedEnumValueExtensions = serializedEnumValueExtensions;
|
||||||
}
|
}
|
||||||
|
@ -284,8 +288,9 @@ public class ProtoTypeAdapter
|
||||||
protoBuilder.setField(fieldDescriptor, fieldValue);
|
protoBuilder.setField(fieldDescriptor, fieldValue);
|
||||||
} else if (fieldDescriptor.isRepeated()) {
|
} else if (fieldDescriptor.isRepeated()) {
|
||||||
// If the type is an array, then we have to grab the type from the class.
|
// 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 =
|
String protoArrayFieldName =
|
||||||
fieldNameSerializationFormat.convert(fieldDescriptor.getName()) + "_";
|
protoFormat.to(CaseFormat.LOWER_CAMEL, fieldDescriptor.getName()) + "_";
|
||||||
Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName);
|
Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName);
|
||||||
Type protoArrayFieldType = protoArrayField.getGenericType();
|
Type protoArrayFieldType = protoArrayField.getGenericType();
|
||||||
fieldValue = context.deserialize(jsonElement, protoArrayFieldType);
|
fieldValue = context.deserialize(jsonElement, protoArrayFieldType);
|
||||||
|
@ -325,7 +330,7 @@ public class ProtoTypeAdapter
|
||||||
return options.getExtension(extension);
|
return options.getExtension(extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fieldNameSerializationFormat.convert(defaultName);
|
return protoFormat.to(jsonFormat, defaultName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,11 @@ message SimpleProto {
|
||||||
optional int32 count = 2;
|
optional int32 count = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ProtoWithDifferentCaseFormat {
|
||||||
|
repeated string name_that_tests_case_format = 1;
|
||||||
|
optional string another_field = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message ProtoWithRepeatedFields {
|
message ProtoWithRepeatedFields {
|
||||||
repeated int64 numbers = 1;
|
repeated int64 numbers = 1;
|
||||||
repeated SimpleProto simples = 2;
|
repeated SimpleProto simples = 2;
|
||||||
|
|
|
@ -15,10 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package com.google.gson.protobuf.functional;
|
package com.google.gson.protobuf.functional;
|
||||||
|
|
||||||
|
import com.google.common.base.CaseFormat;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.protobuf.ProtoTypeAdapter;
|
import com.google.gson.protobuf.ProtoTypeAdapter;
|
||||||
import com.google.gson.protobuf.ProtoTypeAdapter.EnumSerialization;
|
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.ProtoWithRepeatedFields;
|
||||||
import com.google.gson.protobuf.generated.Bag.SimpleProto;
|
import com.google.gson.protobuf.generated.Bag.SimpleProto;
|
||||||
import com.google.protobuf.GeneratedMessage;
|
import com.google.protobuf.GeneratedMessage;
|
||||||
|
@ -32,6 +35,7 @@ import junit.framework.TestCase;
|
||||||
*/
|
*/
|
||||||
public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
|
public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
|
private Gson upperCamelGson;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
|
@ -43,6 +47,14 @@ public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
|
||||||
.setEnumSerialization(EnumSerialization.NUMBER)
|
.setEnumSerialization(EnumSerialization.NUMBER)
|
||||||
.build())
|
.build())
|
||||||
.create();
|
.create();
|
||||||
|
upperCamelGson =
|
||||||
|
new GsonBuilder()
|
||||||
|
.registerTypeHierarchyAdapter(
|
||||||
|
GeneratedMessage.class, ProtoTypeAdapter.newBuilder()
|
||||||
|
.setFieldNameSerializationFormat(
|
||||||
|
CaseFormat.LOWER_UNDERSCORE, CaseFormat.UPPER_CAMEL)
|
||||||
|
.build())
|
||||||
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSerializeRepeatedFields() {
|
public void testSerializeRepeatedFields() {
|
||||||
|
@ -67,4 +79,23 @@ public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
|
||||||
assertEquals("bar", proto.getSimples(0).getMsg());
|
assertEquals("bar", proto.getSimples(0).getMsg());
|
||||||
assertEquals(7, proto.getSimples(1).getCount());
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user