不幸的是,将FieldNamingStrategy 注册到GsonBuilder 并没有多大好处,因为它只会在与预期相反的方向上进行转换:从Java 字段名称到JSON 元素名称。它不能被合理地用于您的目的。
(详细:
翻译请求的结果结束于FieldNamingStrategy.translateName(Field),其中翻译后的名称用于从JsonObject 中获取关联的JSON 元素,该LinkedHashMap<String, JsonElement> 称为members,将JSON 元素名称映射到它们的相关值。翻译后的名称用作members 的get(String) 方法的参数,Gson 没有提供使最终调用不区分大小写的机制。
members 映射填充了对JsonObject.add(String, JsonElement) 的调用,由Streams.parseRecursive(JsonReader) 生成,从JsonReader 检索到的 JSON 元素名称用作“成员”的键。 (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
{
// json = {"field":"one"}
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 代码,那么为了最有效的结果而更改的部分可能是在 JsonReader 中调用 name = nextString((char) quote);。由于nextString(char) 也用于获取 JSON 元素值,我可能只是复制它以获取名称,然后进行一些小的更改以强制元素名称全部小写或全部大写。当然,这种方法会将您的项目锁定到一个 Gson 版本,否则您需要重复此更改才能升级到更新的 Gson 版本。
对于Jackson,不幸的是,情况似乎相似。不幸的是,带有PropertyNamingStrategy 的翻译工作方式大致相同:它们从 Java 字段名称转换为 JSON 元素名称。可用的 JsonParser.Feature 更改都不会自定义 JsonParser 以强制 JSON 元素名称全部为大写或全部小写。