使用 GSON 不解析字段,只保留 json 原始字符串
Posted
技术标签:
【中文标题】使用 GSON 不解析字段,只保留 json 原始字符串【英文标题】:Using GSON do not parse a field, only keep it with the json raw string 【发布时间】:2017-06-29 17:11:53 【问题描述】:在 Java 中使用 GSON 是否有任何注释,我可以在其中指示一个字段,即使它是一个对象,它也应该将其保留为原始字符串。 ?
或者实现这一目标的最简单方法是什么?
//This is the original
@SerializedName("perro")
public Perro perro
//This is what I want to achieve
@SerializedName("perro")
public String perro
So the result should be
perro = ""Users":["Name":"firulais","Raza":"beagle","Name":"Spike","Value":"Terrier"]"
【问题讨论】:
我不明白。 JavaString
将被序列化为 JSON 字符串。你能举个例子说明一下吗?
所以说我有一个 Java 类调用 Animal.java 有很多字段其中一个字段是调用 Perro 它是一个对象,所以如果我有一个 String 响应它实际上是一个 JSON ,那么如果我做了类似 Animal animal = gson.fromJson(response,Animal.class) 的事情,然后我希望 Perro 字段作为 json 原始字符串保存,而不是将其解析为 Perro 对象。
请使用示例 JSON 有效负载编辑您的问题。如果您的字段是Object
类型并且它实际上是JSON 中的JSON 字符串,我相信Gson 将无法解析。如果是Object
,Gson 需要一个 JSON 对象。
所以对象类型的字段我希望它是字符串类型,不解析该字段,只保留该字段特定的原始 Json 字符串
【参考方案1】:
我发现这个工作的唯一方法是使用
public JsonElement perro;
【讨论】:
谢谢,这正是我想要的! 虽然这行得通,但它使用了大量内存,因为 JsonElement 将整个 json 结构作为树保存在内存中。【参考方案2】:根据@mrsegev 的回答,这里有一个更简单的版本(在 Kotlin 中),适用于任意对象:
class RawJsonAdapter: TypeAdapter<String>()
override fun write(out: JsonWriter?, value: String?)
out?.jsonValue(value)
override fun read(reader: JsonReader?): String
return JsonParser().parse(reader).toString()
这利用了在https://github.com/google/gson/pull/667 中添加的JsonWriter#jsonValue()
用法:
@JsonAdapter(RawJsonAdapter::class)
val fieldName: String? = null
【讨论】:
github.com/google/gson/issues/1368#issuecomment-417821473有更新版本 对于 moshi 中的等价物,请参阅 github.com/square/moshi/issues/675#issuecomment-842732058【参考方案3】:基本上,你需要创建一个自定义的gsonTypeAdapter
类,并自己编写从Object到String的转换登录。
然后注释指示使用什么 TypeAdapter 的字段,以便使用 gson 读取/写入它。
此博文中的更多详细信息:Gson TypeAdapter Example
示例:将类对象转换为原始 JSON 字符串
public class StringTypeAdapter extends TypeAdapter<String>
@Override
public void write(JsonWriter out, String value) throws IOException
try
JSONObject jsonObject = new JSONObject(value);
out.beginObject();
Iterator<String> iterator = jsonObject.keys();
while (iterator.hasNext())
String key = iterator.next();
String keyValue = jsonObject.getString(key);
out.name(key).value(keyValue);
out.endObject();
catch (JSONException e)
e.printStackTrace();
@Override
public String read(JsonReader in) throws IOException
in.beginObject();
JSONObject jsonObject = new JSONObject();
while (in.hasNext())
final String name = in.nextName();
final String value = in.nextString();
try
jsonObject.put(name, value);
catch (JSONException e)
e.printStackTrace();
in.endObject();
return jsonObject.toString();
使用 TypeAdapter:
@JsonAdapter(StringTypeAdapter.class)
private String someClass; // Lazy parsing this json
【讨论】:
我尝试使用 TypeAdapter 但如何将 JsonReader 转换为原始字符串? 用一个示例更新了我的答案,将类对象解析为原始 JSON 字符串。 这个不起作用,在读取是否有 JSONObject 作为字符串时,它会出现异常 仅供参考,TypeAdapter 的 write() 方法可以使用jsonValue()
直接发出原始 json。见github.com/google/gson/pull/667【参考方案4】:
你应该可以使用public JsonObject perro;
然后您可以调用gson.toJson(perro)
来获取String
值。
【讨论】:
我尝试使用@SerializedName("perro") public JsonObject perro 但不起作用 @KenenisaBekele 你能包含你正在转换的完整 json 字符串吗...我在一些地方使用我在回答中提到的方法,其中 json 有效负载中的字段包含另一个 json 字符串。 ...但也许你所拥有的并不完全是这种情况。 没有理由再次涉及Gson
实例。只需使用perro.toString()
即可获得String
表示。
@KenenisaBekele 为什么这个答案被否决了。这是一个没有自定义类型适配器的好解决方案。
不起作用 预期为 com.google.gson.JsonObject 但为 com.google.gson.JsonPrimitive以上是关于使用 GSON 不解析字段,只保留 json 原始字符串的主要内容,如果未能解决你的问题,请参考以下文章
在用Gson解析对象的时候,json数据中没有的字段,会赋初值。
使用google的Gson库和alibaba的Fastjson库解析json数据的区别