Skip to content

Commit

Permalink
fix: JSON deserialization setter case priority (#1831)
Browse files Browse the repository at this point in the history
* fix: JSON deserialization setter case priority

Fixes the problem of JSON deserialization ignoring the case of setters.
Now case-sensitive setter method matches are considered first.

Fixes: #1830.

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

---------

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
meltsufin and gcf-owl-bot[bot] committed Mar 14, 2023
1 parent 84216c5 commit 30182e1
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 13 deletions.
Expand Up @@ -134,12 +134,20 @@ public static FieldInfo of(Field field) {
}

/** Creates list of setter methods for a field only in declaring class. */
private Method[] settersMethodForField(Field field) {
private Method[] settersMethodForField(final Field field) {
List<Method> methods = new ArrayList<>();
String fieldSetter = "set" + Ascii.toUpperCase(field.getName().substring(0, 1));
if (field.getName().length() > 1) {
fieldSetter += field.getName().substring(1);
}
for (Method method : field.getDeclaringClass().getDeclaredMethods()) {
if (Ascii.toLowerCase(method.getName()).equals("set" + Ascii.toLowerCase(field.getName()))
&& method.getParameterTypes().length == 1) {
methods.add(method);
if (method.getParameterTypes().length == 1) {
// add case-sensitive matches first in the list
if (method.getName().equals(fieldSetter)) {
methods.add(0, method);
} else if (Ascii.toLowerCase(method.getName()).equals(Ascii.toLowerCase(fieldSetter))) {
methods.add(method);
}
}
}
return methods.toArray(new Method[0]);
Expand Down Expand Up @@ -216,15 +224,13 @@ public Object getValue(Object obj) {
* value.
*/
public void setValue(Object obj, Object value) {
if (setters.length > 0) {
for (Method method : setters) {
if (value == null || method.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
try {
method.invoke(obj, value);
return;
} catch (IllegalAccessException | InvocationTargetException e) {
// try to set field directly
}
for (Method method : setters) {
if (value == null || method.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
try {
method.invoke(obj, value);
return;
} catch (IllegalAccessException | InvocationTargetException e) {
// try to set field directly
}
}
}
Expand Down
Expand Up @@ -14,6 +14,7 @@

package com.google.api.client.util;

import com.google.api.client.json.GenericJson;
import junit.framework.TestCase;

/**
Expand Down Expand Up @@ -49,4 +50,36 @@ public void testEnumValue() {
assertEquals(E.OTHER_VALUE, FieldInfo.of(E.OTHER_VALUE).<E>enumValue());
assertEquals(E.NULL, FieldInfo.of(E.NULL).<E>enumValue());
}

public static final class Data extends GenericJson {
@Key String passcode;
@Key String passCode;

public Data setPasscode(String passcode) {
this.passcode = passcode;
return this;
}

public Data setPassCode(String passCode) {
this.passCode = passCode;
return this;
}
}

public void testSetValueCaseSensitivityPriority() {
Data data = new Data();
data.setPasscode("pass1");
data.setPassCode("pass2");
data.set("passCode", "passX");

assertEquals(data.passcode, "pass1");
assertEquals(data.passCode, "passX");

data.setPasscode("pass1");
data.setPassCode("pass2");
data.set("passcode", "passX");

assertEquals(data.passcode, "passX");
assertEquals(data.passCode, "pass2");
}
}

0 comments on commit 30182e1

Please sign in to comment.