GSON针对特定字段动态将Integer值转换为Boolean值 [英] GSON converting Integer value to Boolean value dynamically for specific fields

查看:816
本文介绍了GSON针对特定字段动态将Integer值转换为Boolean值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何处理获得相同名称但不同类型的字段?我在同一请求中有时从API获取整数值,有时是布尔值.我想知道让Json这样的人时该如何处理.我创建了类型适配器,但是它不起作用

How can I handle getting a field same name but different types? I'm getting sometimes integer value sometimes boolean value from API in the same request. I wonder how to handle when I get Json like these. I created type adapter but it doesn't work

我考虑过创建不同的POJO类.但是,这个问题并不只是一个请求.由于这个原因,我不喜欢创建POJO.顺便说一句,我看到了类似的问题,但是并不能解决我的问题.

I thought about creating different POJO classes. But this problem is not for just one request. I don't prefer to create POJOs for this reason. Btw I saw similar questions but it doesn't fix my problem.

{
  "name" : "john doe",
  "isValid" : true 
}

有时候我会理解

{
  "name" : "john doe",
  "isValid" : 1 
}

获取整数时出现意外的json异常

I am getting unexpected json exception when getting an integer

class XModel{
    private boolean isValid;
    ...
    ...
}

我想为每个请求返回一个布尔值.有人知道如何解决这个问题吗?

I want to return a boolean value for every request. Does anyone know how to solve this problem?

我想通过类型适配器

解决方案:@MichałZiober的回复对我有用.

Solution: @Michał Ziober's respond works for me.

class BooleanJsonDeserializer implements JsonDeserializer<Boolean> {

    private final Set<String> TRUE_STRINGS = new HashSet<>(Arrays.asList("true", "1", "yes"));

    @Override
    public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        System.out.println(json);
        JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
        if (jsonPrimitive.isBoolean()) {
            return jsonPrimitive.getAsBoolean();
        } else if (jsonPrimitive.isNumber()) {
            return jsonPrimitive.getAsNumber().intValue() == 1;
        } else if (jsonPrimitive.isString()) {
            return TRUE_STRINGS.contains(jsonPrimitive.getAsString().toLowerCase());
        }

        return false;
    }
}

推荐答案

如果XModel类不大,您可以编写自定义解串器,如下所示,您可以在其中控制传入元素:

If XModel class is not big you can write your custom deserialiser as below where you have control over incoming element:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        Gson gson = new GsonBuilder()
                .registerTypeAdapter(XModel.class, new XModelJsonDeserializer())
                .create();

        System.out.println(gson.fromJson(new FileReader(jsonFile), XModel.class));
    }
}

class XModelJsonDeserializer implements JsonDeserializer<XModel> {

    private final Set<String> TRUE_STRINGS = new HashSet<>(Arrays.asList("true", "1", "yes"));

    @Override
    public XModel deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        XModel response = new XModel();
        JsonObject jsonResponse = (JsonObject) json;
        response.setName(jsonResponse.get("name").getAsString());
        // other fields

        JsonElement dataElement = jsonResponse.get("isValid");
        if (dataElement.isJsonNull()) {
            response.setValid(false);
        } else if (dataElement.isJsonPrimitive()) {
            JsonPrimitive jsonPrimitive = dataElement.getAsJsonPrimitive();
            if (jsonPrimitive.isBoolean()) {
                response.setValid(jsonPrimitive.getAsBoolean());
            } else if (jsonPrimitive.isNumber()) {
                response.setValid(jsonPrimitive.getAsNumber().intValue() == 1);
            } else if (jsonPrimitive.isString()) {
                response.setValid(TRUE_STRINGS.contains(jsonPrimitive.getAsString()));
            }
            System.out.println("Json data is primitive: " + dataElement.getAsString());
        } else if (dataElement.isJsonObject() || dataElement.isJsonArray()) {
            response.setValid(true); //?!?!
        }

        return response;
    }
}

对于低于JSON的有效载荷:

{
  "name" : "john doe",
  "isValid" : true
}

程序上方的照片:

Json data is primitive: true
XModel{name='john doe', isValid=true}

对于JSON有效负载:

{
  "name" : "john doe",
  "isValid" : 1
}

打印:

Json data is primitive: 1
XModel{name='john doe', isValid=true}

您的模型很清晰,因为所有工作都是在反序列化器级别完成的.

Your model is clear because all work is done on deserialiser level.

稍微精确一点的解决方案是仅序列化primitive.假设模型如下所示:

A little bit much precise solution would be to serialise primitive only. Let's assume that model looks like below:

class XModel {

    private String name;

    @JsonAdapter(value = BooleanJsonDeserializer.class)
    private boolean isValid;

    // getters, setters
}

和我们的BooleanJsonDeserializer反序列化器如下所示:

and our BooleanJsonDeserializer deserialiser looks like below:

class BooleanJsonDeserializer implements JsonDeserializer<Boolean> {

    private final Set<String> TRUE_STRINGS = new HashSet<>(Arrays.asList("true", "1", "yes"));

    @Override
    public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        System.out.println(json);
        JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
        if (jsonPrimitive.isBoolean()) {
            return jsonPrimitive.getAsBoolean();
        } else if (jsonPrimitive.isNumber()) {
            return jsonPrimitive.getAsNumber().intValue() == 1;
        } else if (jsonPrimitive.isString()) {
            return TRUE_STRINGS.contains(jsonPrimitive.getAsString().toLowerCase());
        }

        return false;
    }
}

您只需在模型中使用该适配器注释每个boolean属性,即可使用:1True

You need to only annotate every boolean property with this adapter in your model and it is ready to handle: 1, True, etc.

这篇关于GSON针对特定字段动态将Integer值转换为Boolean值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆