Convert a JSON to a Java list

Asked

Viewed 1,652 times

2

I’m having trouble turning a JSON into a Java list, I tried with GSON and Jackson, but I couldn’t succeed with either. My JSON is formatted like this:

[[["00000000000","00000","Fulano de Souza",""],
["11111111111","111111","Sicrano da Silva",""],["22222222222","","Cilano de Tal","X"]]]

This is my class for JSON:

@JsonDeserialize(using= Deserializador.class)
public class AlunoSGP {
    @JsonProperty("0")
    private String nomeAluno;
    @JsonProperty("1")
    private String cpfAluno;
    @JsonProperty("2")
    private String raAluno;
    @JsonProperty("3")
    private boolean bolsista;

    public AlunoSGP(String nome, String ra, String cpf, String bolsa) {
        this.nomeAluno = nome;
        this.raAluno = ra;
        this.cpfAluno = cpf;

        bolsista = "X".equals(bolsa);
    }

   //Getters e Setters

And my code that deserializes JSON is like this:

    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(AlunoSGP.class, new Deserializador());

    try{
        List<AlunoSGP> lstAlunos = Arrays.asList(mapper.readValue(json, AlunoSGP[].class));
        System.out.println("\nTeste lista");
        for(AlunoSGP aluno : lstAlunos){
            System.out.println(aluno.toString());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

Finally, this is my code for Deserializador customized:

@Override
public AlunoSGP deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
      TreeNode tn = p.readValueAsTree();
      String nomeAluno;
      String raAluno;
      String cpfAluno;
      String bolsaAluno;

      if (tn.get(0) != null) {
        cpfAluno = tn.get(0).toString();
      } else {
        cpfAluno = "Erro nomeAluno";
      }

      if (tn.get(1) != null) {
        raAluno = tn.get(1).toString();
      } else {
        raAluno = "Erro nomeAluno";
      }

      if (tn.get(2) != null) {
        nomeAluno = tn.get(2).toString();
      } else {
        nomeAluno = "Erro nomeAluno";
      }

      if (tn.get(3) != null) {
        bolsaAluno = tn.get(3).toString();
      } else {
        bolsaAluno = "Erro nomeAluno";
      }

      return new AlunoSGP(nomeAluno, raAluno, cpfAluno, bolsaAluno);
}

With this code I can print the Students on my list, but the data is all Erro nomeAluno, that is, my deserializer is returning null in JSON positions, I am totally lost on what to do.

  • As far as I know, JSON is bounded by {...} and not [...], besides "terem": "valores".

  • 2

    @Cypherpotato, there is the JSON list and the JSON object. A JSON object is delimited by {} and is composed of key/value pairs, where the key is a string and a value is an entity. A JSON list is delimited by [] and contains several entities. An entity, in this case, may be an object, a list, or a scalar (such as null, number, string, boolean, or any other that I may have forgotten)

  • 1

    @Cypherpotato, for this case it seems that the most appropriate would be to produce and consume JSON objects (or list of objects, if it can return more than one). Makes more sense than sending arbitrary lists up and down...

  • 2

    @Cypherpotato Complementing Jefferson’s commentary, any of the types defined by JSON syntax is considered valid (i.e., only the string "abc" or the number 123, alone, they are also valid JSON’s). What happens is that 99.999% of Apis return objects (delimited by {}), but nothing prevents the return of a list (delimited by []), or even a simple string or number... Inclusive, depending on the case, is even better. If the API is "api.com/users/qtd_total", why not just return 100 instead of { "qtd_total_users": 100 }? :-)

  • Probable duplicity https://answall.com/questions/329595/ler-json-e-transforma-em-lista-java Here are some answers that might help you.

3 answers

1

Hello,

Maybe you can create your json like this

{
   "alunos":[
      {
         "nomeAluno":"00000000000",
         "cpfAluno":"00000",
         "raAluno":"Fulano de Souza",
         "bolsista":""
      },
      {
         "nomeAluno":"00000000000",
         "cpfAluno":"00000",
         "raAluno":"Fulano de Souza",
         "bolsista":""
      }
   ]
}

Woe to their deserialization classes would look like this


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"nomeAluno",
"cpfAluno",
"raAluno",
"bolsista"
})
public class Aluno {

@JsonProperty("nomeAluno")
private String nomeAluno;
@JsonProperty("cpfAluno")
private String cpfAluno;
@JsonProperty("raAluno")
private String raAluno;
@JsonProperty("bolsista")
private String bolsista;

@JsonProperty("nomeAluno")
public String getNomeAluno() {
return nomeAluno;
}

@JsonProperty("nomeAluno")
public void setNomeAluno(String nomeAluno) {
this.nomeAluno = nomeAluno;
}

@JsonProperty("cpfAluno")
public String getCpfAluno() {
return cpfAluno;
}

@JsonProperty("cpfAluno")
public void setCpfAluno(String cpfAluno) {
this.cpfAluno = cpfAluno;
}

@JsonProperty("raAluno")
public String getRaAluno() {
return raAluno;
}

@JsonProperty("raAluno")
public void setRaAluno(String raAluno) {
this.raAluno = raAluno;
}

@JsonProperty("bolsista")
public String getBolsista() {
return bolsista;
}

@JsonProperty("bolsista")
public void setBolsista(String bolsista) {
this.bolsista = bolsista;
}

}
package com.example;

import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"alunos"
})
public class Alunos {

@JsonProperty("alunos")
private List<Aluno> alunos = null;

@JsonProperty("alunos")
public List<Aluno> getAlunos() {
return alunos;
}

@JsonProperty("alunos")
public void setAlunos(List<Aluno> alunos) {
this.alunos = alunos;
}

}

A very useful website that can help you generate the class from JSON for example is this http://www.jsonschema2pojo.org/

You can use this site https://jsonformatter.curiousconcept.com/ also to validate if your JSON is valid

  • in addition, brackets are used to indicate a list in JSON

  • Thanks for the reply, I forgot to mention that I can’t change the JSON, I don’t have access to the code that formats it, so I have to work with it anyway

  • Hello @Gabrielsandoli I believe your solution is to manipulate json using the String manipulation classes in java, look for Stringbuilder, so that you manipulate JSON after you receive itWith Stringbuilder and its methods you can delete some JSON brackets and even insert text dynamically, so you can format JSON to a suitable pattern.

  • I’ll take a look @Brendoniwata, thank you!

  • @Brendoniwata No need to manipulate the string. The JSON it receives is valid (it only has a "weird" structure, because I don’t see why they did an array inside another one) but anyway it is perfectly possible to read it with the JSON libraries - as I did in my answer, for example :-)

1


First let’s see what your JSON structure looks like (with some explanatory comments):

[  <-- aqui temos um array
    [  <-- dentro desse array, tem outro array
        // e dentro desse segundo array, temos 3 arrays (cada um com os dados de um aluno) 
        ["00000000000", "00000", "Fulano de Souza", ""],
        ["11111111111", "111111", "Sicrano da Silva", ""],
        ["22222222222", "", "Cilano de Tal ", "X"]
    ]
]

According to the JSON syntax, the square brackets [] delimit an array, and its elements are separated by commas (but if you only have one element, you will not have commas, so [1] and [1, 2] are both valid JSON arrays).

That is, you have an array. Inside it, you have only one element, which is another array. And within this second array, you have 3 elements, each of which is also an array (each of which contains a student’s data).


Another way to view this JSON is to analyze from the inside out. First you have an array that represents a student’s data:

["00000000000", "00000", "Fulano de Souza", ""]

You have 3 arrays of this type, which would be the data of 3 students. So your structure can be seen as follows:

[  <-- aqui temos um array
    [  <-- dentro desse array, tem outro array
        // e dentro desse segundo array, temos 3 alunos 
        aluno1, aluno2, aluno3
    ]
]

That is, each student is represented by an array with its data. You have an array with 3 students, and this array is inside another array. That is, you have an array of students.


Jackson

That being said, an alternative would be to read this JSON as an array of arrays, and then take the first element of the array read. With Jackson, would look like this:

// um array de arrays, para corresponder à estrutura do JSON
AlunoSGP[][] array = mapper.readValue(json, AlunoSGP[][].class);

// pega o primeiro elemento do array, que é o array de alunos
List<AlunoSGP> lstAlunos = Arrays.asList(array[0]);

for (AlunoSGP aluno : lstAlunos) {
    System.out.println(aluno.toString());
}

In fact, the list creation is redundant, you could iterate directly through the array:

AlunoSGP[][] array = mapper.readValue(json, AlunoSGP[][].class);
for (AlunoSGP aluno : array[0]) {
    System.out.println(aluno.toString());
}

Another detail is that in your Deserializador you are returning the values with the quotes, then the name is "Fulano" instead of Fulano. An alternative to fix this would be to change it to go through the tokens in the array and populate the student data in a loop:

@Override
public AlunoSGP deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    String[] values = new String[4];
    int i = 0;
    while (true) {
        JsonToken token = p.nextToken();
        if (JsonToken.END_ARRAY.equals(token) || token == null) {
            break;
        }
        values[i++] = p.getValueAsString();
    }
    return new AlunoSGP(values[0], values[1], values[2], values[3]);
}

This does not include validations for the content and size of the array - it assumes that there will always be 4 elements. You can include the validations if you feel it is necessary.


Gson

With Gson, the logic is the same: read JSON as an array of students.

First you create a com.google.gson.JsonDeserializer, that will turn each array into a student:

import com.google.gson.JsonDeserializer;
import com.google.gson.JsonParseException;

public class AlunoDeserializer implements JsonDeserializer<AlunoSGP> {
    @Override
    public AlunoSGP deserialize(JsonElement jsonElement, Type member, JsonDeserializationContext context) throws JsonParseException {
        JsonArray array = jsonElement.getAsJsonArray();
        if (array.size() != 4) {
            // array não tem 4 posições, não dá para criar aluno
            throw new JsonParseException("Faltam dados do aluno");
        }
        // cria o aluno, usando as informações do array
        return new AlunoSGP(array.get(0).getAsString(), array.get(1).getAsString(),
                            array.get(2).getAsString(), array.get(3).getAsString());
    }
}

Then just read JSON as an array of students:

Gson gson = new GsonBuilder()
                // registrar o JsonDeserializer de alunos
                .registerTypeHierarchyAdapter(AlunoSGP.class, new AlunoDeserializer())
                .create();
// ler o JSON como um array de array de alunos
AlunoSGP[][] arrayDeArrayDeAlunos = gson.fromJson(json, AlunoSGP[][].class);
for (AlunoSGP aluno : arrayDeArrayDeAlunos[0]) {
    System.out.println(aluno.toString());
}

Finally, something that is not directly related to the problem. If you have a class called AlunoSGP, it’s kind of redundant that the fields call themselves nomeAluno, cpfAluno, etc. They could call themselves just nome and cpf, because it is already understood that these are data of the student.

  • 1

    Man, I just implemented here and it worked, thank you very much, explained very well, congratulations!

0

Using the Gson I got here, you can do so

Gson gson = new Gson();

Object object = gson.fromJson(new FileReader(filePath), Object.class);

Where filepath is the path where your json file is

Ai you can convert this Object to a list like this

List lista = Arrays.asList(object);

to go through the list you can do so

Iterator it = lista.iterator();
        while (it.hasNext()) {
            List inner = (List) it.next();
            Iterator it2 = inner.iterator();
            while (it2.hasNext()) {
                List inner2 = (List) it2.next();
                for (Object obj : inner2) {
                    System.out.println(obj);
                }

            }
        }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.