如何将缓存的 json 字符串与 gson 一起使用?
Posted
技术标签:
【中文标题】如何将缓存的 json 字符串与 gson 一起使用?【英文标题】:How to use a cached json string with gson? 【发布时间】:2014-01-30 17:31:54 【问题描述】:我有一个保存缓存的 json 字符串的类:
class Foo
private transient String cachedJson; // value = [ "john", "mary" ]
private List<String> names;
当我使用 gson 序列化 Foo 类的实例时,有没有一种方法可以让我拥有一个自定义序列化程序,只需为“名称”字段写入缓存的字符串,而不是让序列化程序重新序列化所有内容?比如:
public class CustomParserFoo implements
JsonSerializer<Foo>
@Override
public JsonElement serialize(Foo src,
Type typeOfSrc,
JsonSerializationContext context)
JsonObject element = new JsonObject();
if (src.cachedJson != null)
// cached value present, use it.
element.addProperty("names", src.cachedJson);
else
// have to really serialize it.
element.addProperty("names", ...);
return element;
上面的问题是gson会尝试转义你提供的字符串(它已经被json转义了)。
用例类似于拥有一个非常大的对象,并且只有一个字段可能会更改,并且您必须经常对其进行序列化 - 所以不必重新序列化整个对象,只需重新序列化属性就好了已经改变了。
谢谢
【问题讨论】:
【参考方案1】:当使用 Gson 进行序列化时,您正在创建一个解析树,而 Gson 负责编写;不幸的是,它不提供告诉它通过您的类中的字段的功能,因为它已经是 JSON。
你必须这样做是使用com.google.gson.JsonParser
类给你一个JsonElement
:
JsonElement cachedArray = new JsonParser().parse(src.cachedJson);
element.addProperty("names", cachedArray);
因为这意味着您正在反序列化缓存的 JSON,以便 gson 稍后可以写出整个解析树,所以将您的 JSON 缓存为 JsonArray
可能更有意义。
编辑添加: 值得一提的是,Jackson JSON 解析器确实提供了这种序列化功能。您可以使用@JsonRawValue
注释字段或方法,然后它会通过它。
【讨论】:
但是这个解决方案确实将String
解析为一个对象,然后将其写入流中。
@SotiriosDelimanolis 非常正确。但真的没有办法解决这个问题。在序列化时使用 Gson,您正在使用解析树,而 gson 负责编写。 OP 缓存 JsonArray
可能更有意义
好吧,是的,我想他们需要通过类似于杰克逊所做的事情进行特殊处理。谢谢!【参考方案2】:
在我们的服务中,我们为每个请求花费 200 毫秒只是对缓存对象进行 gson 序列化。我们更改了架构以缓存 json 字符串并直接返回它们。
您必须重新打包 gson 库并创建自己的:
package repackaged.com.google.gson;
public class JsonElementCache extends JsonElement
String cache;
public JsonElementCache(String cache)
this.cache = cache;
public String getCache()
return cache;
@Override
JsonElement deepCopy()
return new JsonElementCache(this.cache);
这将允许您在 TypeAdapters 类中更改这一行:
@Override public void write(JsonWriter out, JsonElement value) throws IOException
if (value == null || value.isJsonNull())
if (value instanceof JsonElementCache)
out.writeCached(((JsonElementCache) value).getCache());
else if (value == null || value.isJsonNull())
JsonWriter.class 中也是这样:
public void writeCached(String str)
try
writeDeferredName();
beforeValue(false);
out.write(str);
catch (Exception e)
e.printStackTrace();
希望这是有道理的。
【讨论】:
以上是关于如何将缓存的 json 字符串与 gson 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
Gson 无法解析 Kotlin 中的字符串 json 格式数据
一起Talk Android吧(第三百五十三回:Gson库解析JSON数组一)
使用 Gitlab 仪表板 - 如何将 grafonnet 与 jsonnet 一起使用以生成我可以与 Grafana 一起使用的 json 文件