GSON conversión de valor entero a valor booleano dinámicamente para campos específicos

Beyazid:

¿Cómo puedo conseguir una manija mismo nombre de campo, pero diferentes tipos? Me estoy poniendo a veces entero valor booleano veces el valor de la API en la misma petición. Me pregunto cómo manejar cuando llegue JSON como estos. He creado adaptador tipo, pero no funciona

Pensé en la creación de diferentes clases POJO. Sin embargo, este problema no es para una sola petición. No prefiero crear POJOs por esta razón. Por cierto vi preguntas similares pero no soluciona mi problema.

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

en algún momento llego int

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

Me estoy haciendo una excepción inesperada JSON al conseguir un entero

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

Quiero devolver un valor booleano para cada solicitud. ¿Alguien sabe cómo solucionar este problema?

Editar: Quiero prevenir a través de palabras clave instanceOf tipo de adaptador


Solución: @ responden Michał Ziober funciona para mí.

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;
    }
}
Michael Ziober:

Si XModella clase no es grande usted puede escribir su deserialiser costumbre como por debajo de donde usted tiene control sobre el elemento de entrada:

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;
    }
}

Por debajo de JSONla carga útil:

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

programa imprime anteriores:

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

Para JSONla carga útil:

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

huellas dactilares:

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

Su modelo es claro porque todo el trabajo se realiza en el nivel deserialiser.

Un poco más precisa sería la solución a serializar primitivesolamente. Vamos a suponer que las miradas modelo, como a continuación:

class XModel {

    private String name;

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

    // getters, setters
}

y nuestras BooleanJsonDeserializermiradas deserialiser, como a continuación:

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;
    }
}

Sólo necesita para anotar cada booleanpropiedad con este adaptador en su modelo y que está listo para manejar: 1, True, etc.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=188501&siteId=1
Recomendado
Clasificación