很遗憾,使用 GsonBuilder
注册 FieldNamingStrategy
并没有什么用处,因为它只能将 Java 字段名翻译成 JSON 元素名,无法满足您的需求。
具体来说:
翻译请求的结果在 FieldNamingStrategy.translateName(Field)
结束,翻译后的名称用于从 JsonObject
中获取关联的 JSON 元素。该对象有一个 LinkedHashMap<String, JsonElement>
,称为 members
,将 JSON 元素名称映射到它们的关联值。翻译后的名称作为 members
的参数传递给 get(String)
方法,并且 Gson 不提供使此最终调用不区分大小写的机制。
members
映射通过对 JsonObject.add(String, JsonElement)
的调用进行填充,该方法从 Streams.parseRecursive(JsonReader)
调用中获得 JSON 元素名称并将其用作“members”的键。(JsonReader
使用与 JSON 中完全相同的字符,除非发现转义字符“\”)。在整个调用堆栈中,Gson 不提供修改用于填充 members
的键的机制,例如将其全部转换为小写或大写。
类似地,FieldNamingPolicy
的工作方式也相同。
一个合理的解决方案可能是简单地使用自定义反序列化器,如下所示:
input.json:
[
{"field":"one"},
{"Field":"two"},
{"FIELD":"three"},
{"fIElD":"four"}
]
Foo.java:
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.Map.Entry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
public class Foo
{
public static void main(String[] args) throws Exception
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyClass.class, new MyTypeAdapter());
Gson gson = gsonBuilder.create();
MyClass[] myObjects = gson.fromJson(new FileReader("input.json"), MyClass[].class);
System.out.println(gson.toJson(myObjects));
}
}
class MyClass
{
String field;
}
class MyTypeAdapter implements JsonDeserializer<MyClass>
{
@Override
public MyClass deserialize(JsonElement json, Type myClassType, JsonDeserializationContext context)
throws JsonParseException
{
JsonObject originalJsonObject = json.getAsJsonObject();
JsonObject replacementJsonObject = new JsonObject();
for (Entry<String, JsonElement> elementEntry : originalJsonObject.entrySet())
{
String key = elementEntry.getKey();
JsonElement value = originalJsonObject.get(key);
key = key.toLowerCase();
replacementJsonObject.add(key, value);
}
return new Gson().fromJson(replacementJsonObject, MyClass.class);
}
}
或者,你可以先处理原始JSON,将所有元素名称更改为相同的大小写,全部小写或全部大写。然后,将更改后的JSON传递给Gson进行反序列化。这当然会减慢JSON处理速度。
如果您能够更改项目中的Gson代码,则可能需要更改最有效结果的部分是调用name = nextString((char) quote);
在JsonReader
中。由于nextString(char)
也用于获取JSON元素值,我可能只会复制它以获取名称,然后对其进行微小的更改,以强制元素名称全部为小写或全部为大写。当然,这种方法会将您的项目锁定到一个Gson版本,否则您需要重复此更改以升级到新的Gson版本。
使用Jackson,情况似乎非常相似。使用PropertyNamingStrategy
进行翻译的方式不幸地相同:它们从Java字段名称转换为JSON元素名称。没有可用的JsonParser.Feature
更改会自定义JsonParser
以将JSON元素名称强制为全部大写或全部小写。