GSONは、特定のフィールドのために動的にブール値を整数値に変換します

Beyazid:

どのように私は、フィールド名前が同じで異なる種類を取得扱うことができますか?私は、同じリクエストでAPIから値整数時にはブール値を取得しています。私はこれらのようなJSONを取得するときにどのように処理するか疑問に思います。私はタイプのアダプタを作成したが、それは仕事をしません

私は別のPOJOクラスの作成について考えました。しかし、この問題は、ただ一つの要求のためではありません。私はこのような理由のためにPOJOを作成することを好むはありません。ところで私は、同様の質問を見ましたが、それは私の問題を解決していません。

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

いつか私はint型を取得します

{
  "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;
    }
}
マイケルZiober:

場合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、あなたのモデルでは、このアダプタでプロパティを、それがハンドルに準備ができている:1Trueなど

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=188498&siteId=1