mirror of
https://github.com/google/gson.git
synced 2026-03-13 08:01:59 +08:00
Give FieldNamingStrategy the ability to return multiple String names (#2776)
* Give FieldNamingStrategy the ability to return multiple String names * Fixed formatting violations * Code review changes - Changed fieldName to be added first to the fieldName list - test which verifies that when 'alternate names' are configured they don't affect serialization, and only affect deserialization - Updated translateToAlternateNames JavaDoc to refer it works like SerializedName#alternate() * Removed usage of Stream.concat Check Android compatibility test fails when using Stream.concat, switched to traditional Java method. * Code Review Changes 1. Renamed badname to primary-name 2. Added test deserializing TranslateName with translateToAlternateNames * Fixed typo * added @since $next-version$ to translateToAlternateNames method * Renamed translateToAlternateNames to alternateNames * Merged the code with and without the SerializedName annotation * Improved FieldNamingStrategy JavaDoc for the alternateNames method. * Added special handling for annotation without alternate names * Moved Collections.singletonList block to apply to both cases * Update gson/src/main/java/com/google/gson/FieldNamingStrategy.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> * Update gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> * Update gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> * Update gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> * Update gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> --------- Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
This commit is contained in:
@@ -16,7 +16,10 @@
|
||||
|
||||
package com.google.gson;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
|
||||
@@ -37,4 +40,16 @@ public interface FieldNamingStrategy {
|
||||
* @since 1.3
|
||||
*/
|
||||
public String translateName(Field f);
|
||||
|
||||
/**
|
||||
* Returns alternative names for this field when it is being deserialized. This is similar to
|
||||
* {@link SerializedName#alternate()}.
|
||||
*
|
||||
* @param f the field object
|
||||
* @return the list of alternative field names.
|
||||
* @since $next-version$
|
||||
*/
|
||||
default List<String> alternateNames(Field f) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,21 +84,25 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
|
||||
/** first element holds the default name */
|
||||
@SuppressWarnings("MixedMutabilityReturnType")
|
||||
private List<String> getFieldNames(Field f) {
|
||||
|
||||
String fieldName;
|
||||
List<String> alternates;
|
||||
SerializedName annotation = f.getAnnotation(SerializedName.class);
|
||||
if (annotation == null) {
|
||||
String name = fieldNamingPolicy.translateName(f);
|
||||
return Collections.singletonList(name);
|
||||
fieldName = fieldNamingPolicy.translateName(f);
|
||||
alternates = fieldNamingPolicy.alternateNames(f);
|
||||
} else {
|
||||
fieldName = annotation.value();
|
||||
alternates = Arrays.asList(annotation.alternate());
|
||||
}
|
||||
|
||||
String serializedName = annotation.value();
|
||||
String[] alternates = annotation.alternate();
|
||||
if (alternates.length == 0) {
|
||||
return Collections.singletonList(serializedName);
|
||||
if (alternates.isEmpty()) {
|
||||
return Collections.singletonList(fieldName);
|
||||
}
|
||||
|
||||
List<String> fieldNames = new ArrayList<>(alternates.length + 1);
|
||||
fieldNames.add(serializedName);
|
||||
Collections.addAll(fieldNames, alternates);
|
||||
List<String> fieldNames = new ArrayList<>(alternates.size() + 1);
|
||||
fieldNames.add(fieldName);
|
||||
fieldNames.addAll(alternates);
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.common.TestTypes.ClassWithSerializedNameFields;
|
||||
import com.google.gson.common.TestTypes.StringWrapper;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -237,6 +238,78 @@ public class NamingPolicyTest {
|
||||
assertThat(new Gson().toJson(new AtName())).isEqualTo("{\"@foo\":\"bar\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGsonWithNameDeserialiation() {
|
||||
Gson gson =
|
||||
builder
|
||||
.setFieldNamingStrategy(
|
||||
new FieldNamingStrategy() {
|
||||
|
||||
@Override
|
||||
public String translateName(Field f) {
|
||||
return "primary-name";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> alternateNames(Field f) {
|
||||
return List.of("alternate-name");
|
||||
}
|
||||
})
|
||||
.create();
|
||||
String target = "{\"primary-name\":\"someValue\"}";
|
||||
StringWrapper deserializedObject = gson.fromJson(target, StringWrapper.class);
|
||||
assertThat(deserializedObject.someConstantStringInstanceField).isEqualTo("someValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGsonWithAlternateNamesDeserialiation() {
|
||||
Gson gson =
|
||||
builder
|
||||
.setFieldNamingStrategy(
|
||||
new FieldNamingStrategy() {
|
||||
|
||||
@Override
|
||||
public String translateName(Field f) {
|
||||
return "primary-name";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> alternateNames(Field f) {
|
||||
return List.of("alternate-name");
|
||||
}
|
||||
})
|
||||
.create();
|
||||
String target = "{\"alternate-name\":\"someValue\"}";
|
||||
StringWrapper deserializedObject = gson.fromJson(target, StringWrapper.class);
|
||||
assertThat(deserializedObject.someConstantStringInstanceField).isEqualTo("someValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGsonWithAlternateNamesSerialization() {
|
||||
Gson gson =
|
||||
builder
|
||||
.setFieldNamingStrategy(
|
||||
new FieldNamingStrategy() {
|
||||
|
||||
@Override
|
||||
public String translateName(Field f) {
|
||||
return "some-constant-string-instance-field";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> alternateNames(Field f) {
|
||||
return List.of("alternate-name");
|
||||
}
|
||||
})
|
||||
.create();
|
||||
StringWrapper target = new StringWrapper("blah");
|
||||
assertThat(gson.toJson(target))
|
||||
.isEqualTo(
|
||||
"{\"some-constant-string-instance-field\":\""
|
||||
+ target.someConstantStringInstanceField
|
||||
+ "\"}");
|
||||
}
|
||||
|
||||
static final class AtName {
|
||||
@SerializedName("@foo")
|
||||
String f = "bar";
|
||||
|
||||
Reference in New Issue
Block a user