为了账号安全,请及时绑定邮箱和手机立即绑定

GSON 为特定字段动态地将整数值转换为布尔值

GSON 为特定字段动态地将整数值转换为布尔值

偶然的你 2022-07-27 21:40:08
如何处理获得相同名称但不同类型的字段?在同一个请求中,我有时会从 API 获取整数值,有时会获取布尔值。我想知道当我得到这样的 Json 时如何处理。我创建了类型适配器,但它不起作用我考虑过创建不同的 POJO 类。但是这个问题不仅仅针对一个请求。由于这个原因,我不喜欢创建 POJO。顺便说一句,我看到了类似的问题,但它并没有解决我的问题。{  "name" : "john doe",  "isValid" : true }有时我会明白{  "name" : "john doe",  "isValid" : 1 }获取整数时出现意外的 json 异常class XModel{    private boolean isValid;    ...    ...}我想为每个请求返回一个布尔值。有谁知道如何解决这个问题?编辑:我想通过类型适配器防止 instanceOf 关键字解决方案:@Michał Ziober 的回应对我有用。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;    }}
查看完整描述

3 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

如果XModel类不大,您可以编写自定义反序列化器,如下所示,您可以控制传入元素:


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}

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


更精确的解决方案是primitive仅序列化。假设模型如下所示:


class XModel {


    private String name;


    @JsonAdapter(value = BooleanJsonDeserializer.class)

    private boolean isValid;


    // getters, setters

}

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


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在模型中使用此适配器注释每个属性,它就可以处理:1、、True等。


查看完整回答
反对 回复 2022-07-27
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

我不相信执行此映射很容易,但以下内容可能会有所帮助。


public void setIsValid(Object isValid) {

    String isValidString = String.valueOf(isValid).replace("0", "false").replace("1", "true");

    return Boolean.valueOf(isValidString);

}


查看完整回答
反对 回复 2022-07-27
?
隔江千里

TA贡献1906条经验 获得超10个赞

你可以看看Apache Commons Lang BooleanUtilities。有一种方法可以将不同类型的字符串(和其他对象)解析为布尔值。


System.out.println(BooleanUtils.toBoolean(1));

System.out.println(BooleanUtils.toBoolean(true));

System.out.println(BooleanUtils.toBoolean("TrUe"));

System.out.println(BooleanUtils.toBoolean("true"));

输出


true

true

true

true

但是 BooleanUtils.toBoolean("1");,false您可以像这样组合它:


String isValid = jsonPrimitive.get("isValid").getAsString();

System.out.println(BooleanUtils.toBoolean(isValid) || isValid.equals("1"));


查看完整回答
反对 回复 2022-07-27
  • 3 回答
  • 0 关注
  • 112 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信