diff --git a/gson/src/main/java/com/google/gson/FieldNamingStrategy.java b/gson/src/main/java/com/google/gson/FieldNamingStrategy.java index 541588696e..b4c96c29c9 100644 --- a/gson/src/main/java/com/google/gson/FieldNamingStrategy.java +++ b/gson/src/main/java/com/google/gson/FieldNamingStrategy.java @@ -17,6 +17,8 @@ package com.google.gson; 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 @@ -33,8 +35,18 @@ public interface FieldNamingStrategy { * Translates the field name into its JSON field name representation. * * @param f the field object that we are translating - * @return the translated field name. + * @return the list of possible translated field names. * @since 1.3 */ public String translateName(Field f); + + /** + * Translates the field name into its JSON field alternative names representation. + * + * @param f the field object that we are translating + * @return the list of possible translated field names. + */ + default List translateToAlternateNames(Field f) { + return Collections.emptyList(); + } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java index 94396ff1eb..056583a6d7 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java @@ -86,8 +86,10 @@ private boolean includeField(Field f, boolean serialize) { private List getFieldNames(Field f) { SerializedName annotation = f.getAnnotation(SerializedName.class); if (annotation == null) { - String name = fieldNamingPolicy.translateName(f); - return Collections.singletonList(name); + String fieldName = fieldNamingPolicy.translateName(f); + List fieldNames = new ArrayList<>(fieldNamingPolicy.translateToAlternateNames(f)); + fieldNames.add(fieldName); + return fieldNames; } String serializedName = annotation.value(); diff --git a/gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java b/gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java index c419f6155d..a9a705befe 100644 --- a/gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java +++ b/gson/src/test/java/com/google/gson/functional/NamingPolicyTest.java @@ -26,6 +26,7 @@ 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,25 @@ public void testAtSignInSerializedName() { assertThat(new Gson().toJson(new AtName())).isEqualTo("{\"@foo\":\"bar\"}"); } + @Test + public void testGsonWithAlternateNamesDeserialiation() { + Gson gson = builder.setFieldNamingStrategy(new FieldNamingStrategy() { + + @Override + public String translateName(Field f) { + return "badname"; + } + + @Override + public List translateToAlternateNames(Field f) { + return List.of("SomeConstantStringInstanceField"); + } + }).create(); + String target = "{\"SomeConstantStringInstanceField\":\"someValue\"}"; + StringWrapper deserializedObject = gson.fromJson(target, StringWrapper.class); + assertThat(deserializedObject.someConstantStringInstanceField).isEqualTo("someValue"); + } + static final class AtName { @SerializedName("@foo") String f = "bar";