首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用GSON进行JSON序列化时包含某个瞬态字段

在使用GSON进行JSON序列化时包含某个瞬态字段
EN

Stack Overflow用户
提问于 2020-09-18 17:47:30
回答 3查看 315关注 0票数 0

我上过这门课

代码语言:javascript
复制
Myclass
{
  transient String field1;
  transient String field2;
  ... // other non transient fields
}

我存储序列化的对象,以这种方式通过网络使用它们(不包括瞬态字段)。

但是,仅针对一种特殊情况,我需要在序列化中包含field2。

在使用gson进行序列化时,有没有办法不排除某个瞬态字段?

EN

回答 3

Stack Overflow用户

发布于 2020-09-18 18:48:56

解决方案0:

使用类的自定义类型适配器。

考虑

代码语言:javascript
复制
@JsonAdapter(KA.class)
class K{
    private transient String name;
    private transient String password;
}

class Entity_Adapter extends TypeAdapter<Entity>{
    @Override
    public void write(JsonWriter out, Entity value) throws IOException {
        out.beginObject();
        
        out.name("name");
        out.value(value.getName());
        
        out.name("password");
        out.value(value.getPassword());
        
        out.endObject();
    }

    @Override
    public Entity read(JsonReader in) throws IOException {
        Entity k=new Entity();
        in.beginObject();
        
        in.nextName();
        k.setName(in.nextString());
        
        in.nextName();
        k.setPassword(in.nextString());
        
        in.endObject();
        return k;
    }
}

完整示例here

解决方案1: (不健壮)

添加另一个非transient字段,并始终为其复制任何新的field2设置值。例如:

代码语言:javascript
复制
transient String field1;
transient String field2;

@SerializedName("field2")
private String field2_non_trans;

public void setField2(String arg_val){
this.field2 = arg_val;
this.field2_non_trans = arg_val;
}

public String getField2(){
  if(field2 == null){
    field2 = field2_non_trans;
  } 
  return field2;
}

完整示例here

但是,您必须跟踪该field2的每次更改,以使val field2_non_trans的副本始终更新,因此,如果该field2是由构造函数设置的,或者是在其setter函数之外设置的,则必须确保为field2_non_trans设置了值copy

反序列化也是如此,您必须执行以下任一操作:

  • 反序列化完成后,需要使用某个方法将field2_non_trans的反序列化值设为field2
  • 或简单地返回field2_non_trans by getField2()方法,其中field2null

解决方案2:

将该field2标记为非瞬态。

票数 1
EN

Stack Overflow用户

发布于 2020-09-18 18:55:00

您可以使用另一个非瞬态复制您的瞬态字段,并从瞬态字段设置器中写入值。这个想法是在每次瞬态字段更新时更新克隆字段。

票数 0
EN

Stack Overflow用户

发布于 2020-09-18 19:20:46

尽管我永远不会因为这样的问题而建议对不同的库使用相同的类,但是您可以轻松地管理Gson将exclusion strategies应用于被序列化和反序列化的字段的方式。

代码语言:javascript
复制
public final class TransientExclusionStrategy
        implements ExclusionStrategy {

    private static final ExclusionStrategy instance = new TransientExclusionStrategy();

    private TransientExclusionStrategy() {
    }

    public static ExclusionStrategy getInstance() {
        return instance;
    }

    @Override
    public boolean shouldSkipField(final FieldAttributes attributes) {
        @Nullable
        final Expose expose = attributes.getAnnotation(Expose.class);
        if ( expose == null ) {
            return attributes.hasModifier(Modifier.TRANSIENT);
        }
        return !expose.serialize();
    }

    @Override
    public boolean shouldSkipClass(final Class<?> clazz) {
        return false;
    }

}

此实现将通过以下单元测试:

代码语言:javascript
复制
public final class TransientExclusionStrategyTest {

    private static final String EXPOSED = "EXPOSED";
    private static final String IGNORED = "IGNORED";

    @SuppressWarnings("all")
    private static final class MyClass {

        final String s0 = EXPOSED; // no explicit expose, serialized by default

        @Expose(serialize = false)
        final String s1 = IGNORED; // ignored by annotation

        @Expose(serialize = true)
        final String s2 = EXPOSED; // serialized by annotation

        final transient String ts0 = IGNORED; // no explicit expose, ignored by default

        @Expose(serialize = false)
        final transient String ts1 = IGNORED; // ignored by annotation

        @Expose(serialize = true)
        final transient String ts2 = EXPOSED; // serialized by annotation

    }

    @Test
    public void test() {
        final Gson gson = new GsonBuilder()
                .addSerializationExclusionStrategy(TransientExclusionStrategy.getInstance())
                .create();
        final JsonObject json = (JsonObject) gson.toJsonTree(new MyClass());
        for ( final Map.Entry<String, JsonElement> e : json.entrySet() ) {
            final String stringValue = e.getValue().getAsString();
            Assertions.assertEquals(EXPOSED, stringValue, () -> "Expected " + EXPOSED + " but was " + stringValue + " for " + e.getKey());
        }
    }

}

因此,您不需要为每个这样的“特殊”类处理任何特殊的类型适配器,也不需要引入中间字段(这不一定与您正在使用的其他库和框架处于冲突状态)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63953357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档