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

如何处理获得相同名称但不同类型的字段?在同一个请求中,我有时会从 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;

    }

}


偶然的你
浏览 113回答 3
3回答

胡子哥哥

如果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 {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; File jsonFile = new File("./resource/test.json").getAbsoluteFile();&nbsp; &nbsp; &nbsp; &nbsp; Gson gson = new GsonBuilder()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .registerTypeAdapter(XModel.class, new XModelJsonDeserializer())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .create();&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(gson.fromJson(new FileReader(jsonFile), XModel.class));&nbsp; &nbsp; }}class XModelJsonDeserializer implements JsonDeserializer<XModel> {&nbsp; &nbsp; private final Set<String> TRUE_STRINGS = new HashSet<>(Arrays.asList("true", "1", "yes"));&nbsp; &nbsp; @Override&nbsp; &nbsp; public XModel deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {&nbsp; &nbsp; &nbsp; &nbsp; XModel response = new XModel();&nbsp; &nbsp; &nbsp; &nbsp; JsonObject jsonResponse = (JsonObject) json;&nbsp; &nbsp; &nbsp; &nbsp; response.setName(jsonResponse.get("name").getAsString());&nbsp; &nbsp; &nbsp; &nbsp; // other fields&nbsp; &nbsp; &nbsp; &nbsp; JsonElement dataElement = jsonResponse.get("isValid");&nbsp; &nbsp; &nbsp; &nbsp; if (dataElement.isJsonNull()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.setValid(false);&nbsp; &nbsp; &nbsp; &nbsp; } else if (dataElement.isJsonPrimitive()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JsonPrimitive jsonPrimitive = dataElement.getAsJsonPrimitive();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (jsonPrimitive.isBoolean()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.setValid(jsonPrimitive.getAsBoolean());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (jsonPrimitive.isNumber()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.setValid(jsonPrimitive.getAsNumber().intValue() == 1);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (jsonPrimitive.isString()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.setValid(TRUE_STRINGS.contains(jsonPrimitive.getAsString()));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Json data is primitive: " + dataElement.getAsString());&nbsp; &nbsp; &nbsp; &nbsp; } else if (dataElement.isJsonObject() || dataElement.isJsonArray()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.setValid(true); //?!?!&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return response;&nbsp; &nbsp; }}对于以下JSON有效载荷:{&nbsp; "name" : "john doe",&nbsp; "isValid" : true}上面的程序打印:Json data is primitive: trueXModel{name='john doe', isValid=true}对于JSON有效载荷:{&nbsp; "name" : "john doe",&nbsp; "isValid" : 1}印刷:Json data is primitive: 1XModel{name='john doe', isValid=true}您的模型很清楚,因为所有工作都是在反序列化器级别完成的。更精确的解决方案是primitive仅序列化。假设模型如下所示:class XModel {&nbsp; &nbsp; private String name;&nbsp; &nbsp; @JsonAdapter(value = BooleanJsonDeserializer.class)&nbsp; &nbsp; private boolean isValid;&nbsp; &nbsp; // getters, setters}我们的BooleanJsonDeserializer反序列化器如下所示:class BooleanJsonDeserializer implements JsonDeserializer<Boolean> {&nbsp; &nbsp; private final Set<String> TRUE_STRINGS = new HashSet<>(Arrays.asList("true", "1", "yes"));&nbsp; &nbsp; @Override&nbsp; &nbsp; public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(json);&nbsp; &nbsp; &nbsp; &nbsp; JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();&nbsp; &nbsp; &nbsp; &nbsp; if (jsonPrimitive.isBoolean()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return jsonPrimitive.getAsBoolean();&nbsp; &nbsp; &nbsp; &nbsp; } else if (jsonPrimitive.isNumber()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return jsonPrimitive.getAsNumber().intValue() == 1;&nbsp; &nbsp; &nbsp; &nbsp; } else if (jsonPrimitive.isString()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return TRUE_STRINGS.contains(jsonPrimitive.getAsString().toLowerCase());&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }}您只需要boolean在模型中使用此适配器注释每个属性,它就可以处理:1、、True等。

慕虎7371278

我不相信执行此映射很容易,但以下内容可能会有所帮助。public void setIsValid(Object isValid) {&nbsp; &nbsp; String isValidString = String.valueOf(isValid).replace("0", "false").replace("1", "true");&nbsp; &nbsp; return Boolean.valueOf(isValidString);}

隔江千里

你可以看看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"));输出truetruetruetrue但是 BooleanUtils.toBoolean("1");,false您可以像这样组合它:String isValid = jsonPrimitive.get("isValid").getAsString();System.out.println(BooleanUtils.toBoolean(isValid) || isValid.equals("1"));
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java