【问题标题】:Add excluded field from GsonBuilder back into the object将 GsonBuilder 中的排除字段添加回对象
【发布时间】:2020-11-04 17:58:26
【问题描述】:

所以我使用下面的代码来排除已经序列化的特定字段再次序列化,所以我使用了Gson 中的ExclusionStrategy 来做到这一点。但是现在在没有特定字段的情况下对对象进行序列化后,我该如何将该字段添加回serialized object

这里是exclusion strategy的代码:

 val gson = GsonBuilder().addSerializationExclusionStrategy(object :
          ExclusionStrategy {
          override fun shouldSkipField(f: FieldAttributes?): Boolean {

                return f?.name?.toLowerCase()?.contains("subdata")!!//the field to be skipped
           }

           override fun shouldSkipClass(clazz: Class<*>?): Boolean {
              return false
            }
         }).create()

所以这个对象(数据)包含上面提到的字段subdata,但是在序列化过程中,我将subdata字段取出,因为它已经是serialized

 val serializedData = gson.toJson(Data)
 println("serializedData -> $serializedData")

当我打印 serializedData 时,它仍然不包括 subData

我的问题是,在Data 变成serialized 之后,有没有办法将我上面忽略的subdata 放回serializedData

我们将不胜感激任何帮助或建议。

【问题讨论】:

  • “已经序列化”是什么意思?除非您使用 ExclusionStrategy,否则 Gson 通常会为您发出两次相同的字段吗?还是您的意思是subdata 已经是JSON 数据,您想阻止Gson 将其编码为JSON 字符串?
  • @Marcono1234 子数据已经是 JSON 数据,因为我在该数据上使用了 Gson().toJson(subData)。所以我想阻止 Gson 再次将其编码为 JSON 字符串,因为这样我得到了它的转义数据,并且我不希望它再次被编码。

标签: android kotlin serialization gson


【解决方案1】:

Gson 的ExclusionStrategy 用于完全排除一个类或字段。但是,对于您的用例,您不想排除该字段,而是编写已序列化的 JSON 数据。

这可以通过创建自定义TypeAdapter 并让它使用JsonWriter.jsonValue(...) 来实现。但要小心,因为(尽管没有记录)只有当您写入java.io.Writer(或String 或类似的),序列化为JsonElement(例如,使用Gson.toJsonTree(...))时,才支持此方法将抛出异常,另见this pull request

为了不必为完整的Data 类编写TypeAdapter,您可以将@JsonAdapter 注释用于包含序列化JSON 的字段(对您来说是subdata)。

遗憾的是,我对 Kotlin 还不够熟悉,但下面的 Java 示例可能还是有帮助的:

class LiteralJsonAdapter extends TypeAdapter<String> {
    @Override
    public void write(JsonWriter out, String value) throws IOException {
        // Also encodes null as JSON null
        out.jsonValue(value);
    }

    @Override
    public String read(JsonReader in) throws IOException {
        // JsonReader does not support reading raw JSON data, so would have
        // to deserialize it and afterwards serialize it again
        throw new UnsupportedOperationException("Deserialization is not supported");
    }
}

// Your class
class Data {
    @JsonAdapter(LiteralJsonAdapter.class)
    String subdata;

    // Other fields ...
}

如果您还想支持反序列化,则必须调整 TypeAdapter 或使用 TypeAdapterFactory

尽管重新考虑subdata 是否真的必须包含 JSON 数据可能会更好。当数据不是来自受信任的来源时,您还必须小心,因为JsonWriter.jsonValue(...) 不提供安全保证,它可以注入任意(不限于单个值)甚至格式错误的 JSON 数据。

【讨论】:

  • 您是传奇先生。这很有帮助。非常感谢您的时间和努力。
猜你喜欢
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
  • 2021-06-24
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多