GSON:在不使用全局serializeNulls()的情况下序列化单个空字段

时间:2016-01-26 02:30:53

标签: android json gson

我正在使用Gson和Retrofit,我有一个案例需要序列化一个空字段,但是我无法打开Gson的全局serializeNulls()标志,因为它会破坏我的其余代码。有谁知道如何做到这一点?

这是我尝试过的:

  • 制作注释@SerializeNull。这将是理想的解决方案,但它失败了,因为serializeNulls标志实际上在JsonWriter上,它是ExclusionStrategy的下游。
  • 使用TypeAdapterFactory。同样,JsonWriter是下游的。

我也找不到添加到序列化json的方法,因为它全部发生在Retrofit中。

2 个答案:

答案 0 :(得分:1)

我通过在TypeAdapter.write()中设置setSerializeNulls(true)并将原始值恢复为JsonWriter解决了这个问题:

public class NullableDoubleAdapter extends TypeAdapter<NullableDouble> {

  @Override
  public void write(final JsonWriter out, final NullableDouble value) throws IOException {
    if (value == null) {
      boolean serializeNulls = out.getSerializeNulls();
      out.setSerializeNulls(true);
      out.nullValue();
      out.setSerializeNulls(serializeNulls);
    } else {
      out.value(value.getValue());
    }
  }
...

答案 1 :(得分:0)

这是Andriy解决方案的扩展,它不仅适用于NullableDouble,而且允许一般包装任何类型。与普通serializeNulls()相比,它的缺点是它需要创建GsonForceNull实例作为包装并在整个Java代码中访问value内部(尽管合适的getter / setter实现可以隐藏该细节)

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;

// Forces Gson to output `null` in case the value is null, rather than omitting the field altogether.
public class GsonForceNull<V> {
    public V value;

    public GsonForceNull() {
    }

    public GsonForceNull(V value) {
        this.value = value;
    }

    static class ForceNullTypeAdapterFactory implements TypeAdapterFactory {
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            if (type.getRawType() != GsonForceNull.class) return null;
            //noinspection unchecked
            return this.createInternal(gson,
                    (TypeToken) TypeToken.get(((ParameterizedType) type.getType()).getActualTypeArguments()[0]));
        }

        private <V> TypeAdapter<GsonForceNull<V>> createInternal(Gson gson, TypeToken<V> innerType) {
            final TypeAdapter<V> delegate = gson.getDelegateAdapter(this, innerType);
            return new TypeAdapter<GsonForceNull<V>>() {
                @Override
                public void write(JsonWriter out, GsonForceNull<V> value) throws IOException {
                    V innerValue = value == null ? null : value.value;
                    if (innerValue == null && !out.getSerializeNulls()) {
                        out.setSerializeNulls(true);
                        out.nullValue();
                        out.setSerializeNulls(false);
                    } else {
                        delegate.write(out, innerValue);
                    }
                }

                @Override
                public GsonForceNull<V> read(JsonReader in) throws IOException {
                    return new GsonForceNull<>(delegate.read(in));
                }
            };
        }
    }
}

使用示例:

gsonBuilder.registerTypeAdapterFactory(new GsonForceNull.ForceNullTypeAdapterFactory());

class MyExampleRequestClass {
    private final GsonForceNull<Long> someField = new GsonForceNull<>();
    // getter/setter
}