Java GSON:如何从Json获取不区分大小写的元素?
当Java GSON:如何从Json获取不区分大小写的元素?,java,json,gson,case-insensitive,Java,Json,Gson,Case Insensitive,当JSON对象在传递给方法时包含jsonKey时,下面显示的代码运行良好。我想知道。。。是否有办法获得分配给键的不区分大小写表示形式的值 示例: public String getOutputEventDescription(JsonElement outputEvent) throws ParserException { return retrieveString(outputEvent, DESCRIPTION); } [ {"field":"one"}, {"Field":"
JSON
对象在传递给方法时包含jsonKey
时,下面显示的代码运行良好。我想知道。。。是否有办法获得分配给键的不区分大小写表示形式的值
示例:
public String getOutputEventDescription(JsonElement outputEvent) throws ParserException {
return retrieveString(outputEvent, DESCRIPTION);
}
[
{"field":"one"},
{"Field":"two"},
{"FIELD":"three"},
{"fIElD":"four"}
]
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);
}
}
无论描述是定义为“描述”、“描述”还是“描述”,都应起作用
不幸的是,在当前的实现中似乎没有办法做到这一点。如果您查看Gson源代码,更具体地说,查看JsonObject实现,您将看到底层数据结构是一个链接的哈希映射。get调用只调用映射上的get,而映射又使用密钥的哈希代码和equals方法来查找要查找的对象
唯一的解决方法是为密钥强制执行一些命名约定。最简单的方法是强制所有键使用小写。如果您需要混合大小写密钥,那么您将有更大的困难,需要编写更复杂的算法来转换密钥,而不是简单地调用jsonKey.toLowerCase()。不幸的是,在
GsonBuilder
中注册a不会有多大好处,因为它的翻译方向与预期相反:从Java字段名到JSON元素名。它不能合理地用于您的目的
(详情:
翻译请求的结果在FieldNamingStrategy.translateName(字段)处结束
,其中翻译后的名称用于从JsonObject
获取关联的JSON元素,该对象具有名为members
的LinkedHashMap
,将JSON元素名称映射到其关联值。翻译后的名称用作get(字符串)的参数
成员的方法,Gson没有提供使此最终调用不区分大小写的机制
members
映射中填充了对JsonObject.add(String,jsoneelement)
的调用,该调用由Streams.parseRecursive(JsonReader)
生成,从JsonReader
检索的JSON元素名称用作“members”的键。(JsonReader
使用的字符与JSON中的字符完全相同,但转义字符“\”除外。)在整个调用堆栈中,Gson不提供任何机制来更改用于填充成员的键,例如,使其全部为小写或大写
FieldNamingPolicy
的工作方式相同。)
一个合理的解决方案可能是简单地使用自定义反序列化程序,如下所示
input.json:
public String getOutputEventDescription(JsonElement outputEvent) throws ParserException {
return retrieveString(outputEvent, DESCRIPTION);
}
[
{"field":"one"},
{"Field":"two"},
{"FIELD":"three"},
{"fIElD":"four"}
]
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);
}
}
Foo.java:
public String getOutputEventDescription(JsonElement outputEvent) throws ParserException {
return retrieveString(outputEvent, DESCRIPTION);
}
[
{"field":"one"},
{"Field":"two"},
{"FIELD":"three"},
{"fIElD":"four"}
]
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);
}
}
导入java.io.FileReader;
导入java.lang.reflect.Type;
导入java.util.Map.Entry;
导入com.google.gson.gson;
导入com.google.gson.GsonBuilder;
导入com.google.gson.JsonDeserializationContext;
导入com.google.gson.JsonDeserializer;
导入com.google.gson.JsonElement;
导入com.google.gson.JsonObject;
导入com.google.gson.JsonParseException;
公开课Foo
{
公共静态void main(字符串[]args)引发异常
{
GsonBuilder GsonBuilder=新的GsonBuilder();
gsonBuilder.registerTypeAdapter(MyClass.class,新的MyTypeAdapter());
Gson-Gson=gsonBuilder.create();
MyClass[]myObjects=gson.fromJson(新文件读取器(“input.json”)、MyClass[].class);
System.out.println(gson.toJson(myObjects));
}
}
类MyClass
{
字符串字段;
}
类MyTypeAdapter实现JsonDeserializer
{
@凌驾
公共MyClass反序列化(JsonElement json,类型myClassType,JsonDeserializationContext)
抛出JsonParseException
{
//json={“字段”:“一”}
JsonObject originalJsonObject=json.getAsJsonObject();
JsonObject replacementJsonObject=新建JsonObject();
for(Entry elementEntry:originalJsonObject.entrySet())
{
String key=elementEntry.getKey();
JsonElement value=originalJsonObject.get(键);
key=key.toLowerCase();
replacementJsonObject.add(键,值);
}
返回新的Gson().fromJson(replacementJsonObject,MyClass.class);
}
}
或者,您可以首先处理原始JSON,将所有元素名称更改为相同大小写,全部为小写或大写。然后,将更改后的JSON传递给Gson进行反序列化。这当然会降低JSON处理的速度
如果您能够为您的项目更改Gson代码,那么为了获得最有效的结果,可能需要更改的部分是调用name=nextString((char)quote);JsonReader
。因为nextString(char)
也用于获取JSON元素值,我可能只需要复制它来获取名称,然后做一些小的更改,强制元素名称全部小写或大写。当然,这种方法会将您的项目锁定到一个Gson版本,否则您需要重复此更改以升级到一个较新的Gson版本
不幸的是,情况与之类似。翻译的工作方式非常相似:它们从Java字段名转换为JSON元素名。任何可用的JsonParser.Feature
更改都不会自定义JsonParser
以强制将JSON元素名转换为所有较高或较低的case.我也遇到了类似的问题。我这样做是为了解决这个问题。(将所有键替换为相应的小写版本,并在匹配的类中包含所有小写字段)。希望这能有所帮助
input = input.replaceAll("\\s","");
Matcher m = Pattern.compile("\"\\b\\w{1,}\\b\"\\s*:").matcher(input);
StringBuilder sanitizedJSON = new StringBuilder();
int last = 0;
while (m.find()) {
sanitizedJSON.append(input.substring(last, m.start()));
sanitizedJSON.append(m.group(0).toLowerCase());
last = m.end();
}
sanitizedJSON.append(input.substring(last));
input = sanitizedJSON.toString();
当我遇到一个问题时,我偶然发现了这个问题,在两个端点使用了不同的命名约定,并随后发现了一个侵入性较小的解决方案
Gson确实支持设置命名约定,在序列化和反序列化时,从Java模型名称映射到JSON名称时使用