为动态类型实现自定义GsonCoverterFactory / Deserializer

时间:2018-04-25 04:01:18

标签: android json gson json-deserialization

如何为具有动态值的类型实现自定义GsonConverterFactor或JsonDeserializer?

例如:

如果Tags对象包含内容,则如下所示:

"tags": [
                {
                    "content_id": "13",
                    "tag_id": "3",
                    "created": "2018-03-26 11:09:08",
                    "tag_name": "FICTION"
                },
                {
                    "content_id": "13",
                    "tag_id": "7",
                    "created": "2018-03-26 11:09:08",
                    "tag_name": "JUVENILE FICTION"
                }
            ]

但是,如果它是空的,它将返回:

            "tags": false

基本上,如果解串器将其值读为null,我想制作标记列表false

编辑:我正在使用Retrofit和GSON。

3 个答案:

答案 0 :(得分:2)

您可以像这样创建一个反序列化器

public class UserResponseDeserializer implements 
JsonDeserializer<ResponseWrapper> {
@Override
public ResponseWrapper deserialize(JsonElement json, Type typeOfT, 
JsonDeserializationContext context) throws JsonParseException {


    if (((JsonObject) json).get("tags") instanceof JsonArray){
        return new Gson().fromJson(json, ResponseArray.class);
    } else {
        return new Gson().fromJson(json, ResponseBoolean.class);
    }

}
}

其中ResponseArrayResponseBoolean延伸ResponseWrapper如上所述here

答案 1 :(得分:1)

public class Example implements Serializable
{
@JsonProperty("tags")
private Map<String, Object> tags = new HashMap<String, Object>();
}

使用上面的类进行json解析:

Object object = tags.get("tags");

if (object instanceof JSONArray){
            JSONArray jsonArray = (JSONArray) tags.get("tags");
        }else {
            boolean booleanValue = (boolean) tags.get("tags");
        }

答案 2 :(得分:1)

类型适配器是Gson序列化/反序列化的核心,几乎可以在所有情况下提供帮助。 您只需要实现一个。

final class CollectionFalseAsNullTypeAdapterFactory
        implements TypeAdapterFactory {

    private static final TypeAdapterFactory instance = new CollectionFalseAsNullTypeAdapterFactory();

    private CollectionFalseAsNullTypeAdapterFactory() {
    }

    static TypeAdapterFactory get() {
        return instance;
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        if ( !Collection.class.isAssignableFrom(typeToken.getRawType()) ) {
            return null;
        }
        @SuppressWarnings("unchecked")
        final TypeAdapter<Collection<Object>> delegateTypeAdapter = (TypeAdapter<Collection<Object>>) gson.getDelegateAdapter(this, typeToken);
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) new CollectionFalseAsNullTypeAdapter<>(delegateTypeAdapter);
        return typeAdapter;
    }

    private static final class CollectionFalseAsNullTypeAdapter<E>
            extends TypeAdapter<Collection<E>> {

        private final TypeAdapter<Collection<E>> delegateTypeAdapter;

        private CollectionFalseAsNullTypeAdapter(final TypeAdapter<Collection<E>> delegateTypeAdapter) {
            this.delegateTypeAdapter = delegateTypeAdapter;
        }

        @Override
        public void write(final JsonWriter out, final Collection<E> value)
                throws IOException {
            delegateTypeAdapter.write(out, value);
        }

        @Override
        public Collection<E> read(final JsonReader in)
                throws IOException {
            // Let's just make sure it's a boolean
            if ( in.peek() == JsonToken.BOOLEAN ) {
                // If yes, then just return a null skipping the boolean
                in.skipValue();
                return null;
            }
            return delegateTypeAdapter.read(in);
        }

    }

}

使用示例:

private static final Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd HH:mm:ss")
        .registerTypeAdapterFactory(CollectionFalseAsNullTypeAdapterFactory.get())
        .create();

public static void main(final String... args)
        throws IOException {
    for ( final String resourceName : ImmutableList.of("non-null.json", "null.json") ) {
        try ( final JsonReader jsonReader = Resources.getPackageResourceJsonReader(Q50013856.class, resourceName) ) {
            final Entity entity = gson.fromJson(jsonReader, Entity.class);
            System.out.println(entity);
        }
    }
}

示例输出(假设覆盖了toString):

  

实体{tags = [Tag {contentId = 13,tagId = 3,created = Mon Mar 26 11:09:08 EEST 2018,tagName = FICTION},标签{contentId = 13,tagId = 7,created = Mon Mar 26 11:09:08 EEST 2018,tagName = JUVENILE FICTION}]}
  实体{tags = null}

请注意,您可以注释tags字段更准确,而不是在全球注册工厂:

@JsonAdapter(CollectionFalseAsNullTypeAdapterFactory.class)
final List<Tag> tags = null;