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/FieldNamingPolicyTest.java b/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java index 0d085269f8..73f3b87dd0 100644 --- a/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java +++ b/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java @@ -103,8 +103,7 @@ class Dummy { for (FieldNamingPolicy policy : policies) { // Should ignore default Locale assertWithMessage("Unexpected conversion for %s", policy) - .that(policy.translateName(field)) - .matches(expected); + .that(policy.translateName(field)).matches(expected); } } finally { Locale.setDefault(oldLocale); @@ -142,8 +141,7 @@ class Dummy { for (FieldNamingPolicy policy : policies) { // Should ignore default Locale assertWithMessage("Unexpected conversion for %s", policy) - .that(policy.translateName(field)) - .matches(expected); + .that(policy.translateName(field)).matches(expected); } } finally { Locale.setDefault(oldLocale); diff --git a/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java b/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java index 2a067471ad..adc79ee41d 100644 --- a/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java +++ b/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java @@ -39,6 +39,7 @@ import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.lang.reflect.Type; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; 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";