如何在自定义解串器Gson中使用JsonElement值? [英] How to lowercase the JsonElement value in the custom deserializer Gson?
问题描述
private class HolderDeserializer实现了JsonDeserializer< Holder> {
就像这样
@Override
public Holder deserialize(JsonElement json,Type type,JsonDeserializationContext context)
throws JsonParseException {
Type mapType = new TypeToken< Map< ; String,String>>(){} .getType();
//在下面的数据图中,我希望将值存储为小写
//我该怎么做?
Map< String,String> data = context.deserialize(json,mapType);
返回新的Holder(数据);
$ b $ p
$ b这就是我在注册我的反序列化器时创建Gson对象:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Holder.class,new HolderDeserializer());
Gson gson = gsonBuilder.create();
最后,解析我的JSON,如下所示:
键入responseType = new TypeToken< Map< String,Holder>>(){} .getType();
地图< String,Holder> response = gson.fromJson(jsonLine,responseType);
在我的
deserialize
方法中, code> json{linkedTo:COUNT}
,然后将它载入数据映射为{linkedTo = COUNT}
。我想看看是否有任何方法可以使data
map的所有值都小写,所以不是这个{linkedTo = COUNT}
,它应该自动保存在数据图中的这个{linkedTo = count}
?
有没有办法在Gson中自动执行此操作?
更新:
以下是我的JSON内容:
{
abc:{
linkedTo:COUNT,
//可能更多数据...
},
plmtq:{
linkedTo:TITLE,
decode:TRUE,
//可能更多数据...
}
}
$ c $首先,建议使用Gson
I have a custom deserializer for my class as shown below:
private class HolderDeserializer implements JsonDeserializer<Holder> { @Override public Holder deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { Type mapType = new TypeToken<Map<String, String>>() {}.getType(); // in the below data map, I want value to be stored in lowercase // how can I do that? Map<String, String> data = context.deserialize(json, mapType); return new Holder(data); } }
And this is how I register my deserializer when creating the Gson object:
GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Holder.class, new HolderDeserializer()); Gson gson = gsonBuilder.create();
And finally, parsing my JSON like this:
Type responseType = new TypeToken<Map<String, Holder>>() {}.getType(); Map<String, Holder> response = gson.fromJson(jsonLine, responseType);
In my
deserialize
method, value ofjson
is coming as like this{"linkedTo":"COUNT"}
and then it get loaded into data map as{linkedTo=COUNT}
. I wanted to see if there is any way by which all the value ofdata
map can be lowercase so instead of this{linkedTo=COUNT}
, it should get stored like this{linkedTo=count}
in data map automatically?Is there any way to do this in Gson itself automatically?
Update:
Below is my JSON content:
{ "abc": { "linkedTo": "COUNT", // possibly more data... }, "plmtq": { "linkedTo": "TITLE", "decode": "TRUE", // possibly more data... } }
解决方案Firstly, it is suggested to use Gson TypeAdapter instead of JsonDeserializer. So I'm going to answer your question with it:
New applications should prefer TypeAdapter, whose streaming API is more efficient than this interface's tree API.
Question: How can we modify the json content before deserialization ?
One of the solutions: Preprocess the json content before deserialization and modify some of its contents.
How can we achive this with TypeAdapter: Define a custom
TypeAdapter
, get the json content at itsread
method (which is called just before the deserialization) and modify the content.Code sample:
Define a
TypeAdapterFactory
and aTypeAdapter
;TypeAdapterFactory myCustomTypeAdapterFactory = new TypeAdapterFactory() { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class); final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); // return new TypeAdapter<T>() { public void write(JsonWriter out, T value) throws IOException { JsonElement tree = delegate.toJsonTree(value); beforeWrite(value, tree); elementAdapter.write(out, tree); } public T read(JsonReader in) throws IOException { JsonElement tree = elementAdapter.read(in); afterRead(tree); return delegate.fromJsonTree(tree); } /** * Modify {@code toSerialize} before it is written to * the outgoing JSON stream. */ protected void beforeWrite(T source, JsonElement toSerialize) { } /** * Modify {@code deserialized} before it is parsed */ protected void afterRead(JsonElement deserialized) { if(deserialized instanceof JsonObject) { JsonObject jsonObject = ((JsonObject)deserialized); Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet(); for(Map.Entry<String,JsonElement> entry : entrySet){ if(entry.getValue() instanceof JsonPrimitive) { if(entry.getKey().equalsIgnoreCase("linkedTo")) { String val = jsonObject.get(entry.getKey()).toString(); jsonObject.addProperty(entry.getKey(), val.toLowerCase()); } } else { afterRead(entry.getValue()); } } } } }; } };
We've added an extra process before deserialization. We get the
entrySet
from json content and updatedlinkedTo
key's value.Working sample:
String jsonContent = "{\"abc\":{\"linkedTo\":\"COUNT\"},\"plmtq\":{\"linkedTo\":\"TITLE\",\"decode\":\"TRUE\"}}"; GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapterFactory(myCustomTypeAdapterFactory); Gson gson = gsonBuilder.create(); Map mapDeserialized = gson.fromJson(jsonContent, Map.class);
Output:
This is the similar answer for your question.
这篇关于如何在自定义解串器Gson中使用JsonElement值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!