es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Deserializando JSON con una matriz de No Member Name en un objeto Java personalizado.

Tengo un archivo JSON largo con diferentes tipos de objetos que necesito crear a partir de él.
Dos tipos de objetos personalizados se dan como un arreglo de cadenas y un arreglo de enteros:

"Custom1": ["type1", "type1", "type2", "type3"]
"Custom2": [10,10,20,20,20]

Custom1 y Custom2 tienen sus propias clases con constructores.

He creado una clase Wrapper que maneja el almacenamiento de todos los objetos que Gson crea usando el archivo JSON que tengo. Todos los objetos que tienen nombres de miembros funcionan como se espera.

Cuando intento esto en el Wrapper:

ArrayList<custom1> cusOne;
ArrayList<custom2> cusTwo;

Obtengo una larga cadena de errores. Estos objetos tienen constructores que reciben una cadena / entero (respectivamente).

Pero cuando uso esto en el wrapper:

ArrayList<string> GPUS;
ArrayList<integer> CPUS;

Funciona. Me gustaría que los objetos personalizados se creen directamente en el wrapper y evitar crearlos después. Siento que eso es algo que debería ser posible, pero no pude encontrar información al respecto. Agradecería cualquier consejo sobre cómo se puede hacer.

El código:

public static class Wrapper { // etc objects are the ones I can create normally.
    ArrayList<etc> Etc; 
    ArrayList<string> CusOne;
    ArrayList<integer> CusTwo;
    ArrayList<etc2> Etc2;
    int Etc3;
    int Etc4;
}
public static void main(String[] args) {

    Gson gson = new Gson();
    Wrapper wrapper;
    try {
        wrapper = gson.fromJson(new FileReader(args[0]), Wrapper.class);
        System.out.println(gson.toJson(wrapper));
    } catch (IOException e){
        System.out.println("IOException");
    }
}
public class Custom1 {
    /**
     * Enum que representa el tipo del objeto personalizado.
     */
    enum Type {type1, type2, type3}

    private Type type;
    private Model model;
    private Cluster cluster;
    // constructores, getters y setters
}

public class Custom2 {
    private int count;
    private Vector<databatch> data;
    private Cluster cluster;
    // constructores, getters y setters
}

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para crear los objetos custom directamente en el Wrapper, puedes definir deserializadores personalizados para cada una de las clases Custom que tomen el JSON array apropiado como entrada y lo utilicen para instanciar los objetos.

    Aquí tienes un ejemplo de cómo podrías modificar tu clase Wrapper para hacer esto:

    public static class Wrapper {
        ArrayList<etc> Etc;
        ArrayList<custom1> CusOne;
        ArrayList<custom2> CusTwo;
        ArrayList<etc2> Etc2;
        int Etc3;
        int Etc4;
    
        // deserializador personalizado para Custom1
        public static class Custom1Deserializer implements JsonDeserializer<custom1> {
            public Custom1 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                    throws JsonParseException {
                JsonArray array = json.getAsJsonArray();
                String[] values = new String[array.size()];
                for (int i = 0; i < values.length; i++) {
                    values[i] = array.get(i).getAsString();
                }
                return new Custom1(values);
            }
        }
    
        // deserializador personalizado para Custom2
        public static class Custom2Deserializer implements JsonDeserializer<custom2> {
            public Custom2 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                    throws JsonParseException {
                JsonArray array = json.getAsJsonArray();
                int[] values = new int[array.size()];
                for (int i = 0; i < values.length; i++) {
                    values[i] = array.get(i).getAsInt();
                }
                return new Custom2(values);
            }
        }
    }
    
    

    Luego, cuando creas tu instancia de Gson, puedes registrar estos deserializadores:

    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(Custom1.class, new Wrapper.Custom1Deserializer());
    builder.registerTypeAdapter(Custom2.class, new Wrapper.Custom2Deserializer());
    Gson gson = builder.create();
    

    Ahora, al deserializar tu archivo JSON en un objeto Wrapper, se utilizará el deserializador personalizado correspondiente para crear los objetos Custom directamente dentro del Wrapper.

    Wrapper wrapper;
    try {
        wrapper = gson.fromJson(new FileReader(args[0]), Wrapper.class);
        System.out.println(gson.toJson(wrapper));
    } catch (IOException e){
        System.out.println("IOException");
    }
    

    Ten en cuenta que en este ejemplo, asumí que los constructores de Custom1 y Custom2 toman arrays de strings e ints respectivamente como entrada. Necesitarás modificar los deserializadores si tus constructores tienen firmas diferentes.

Comments are closed.