How to create a list from a JSON with Javascript?

Asked

Viewed 1,319 times

5

Suppose I have the following given JSON:

const dados = {"animais":[
  {
    "id":1,
    "tipo":"Cachorro",
    "nome":"Max",
    "tags":"Border Collier"
  },{
    "id":2,
    "tipo":"Cachorro",
    "nome":"Fini",
    "tags":"Lhasa Apso"
  },{
    "id":3,
    "tipo":"Gato",
    "nome":"Luna",
    "tags":"Siames"
  },{
    "id":4,
    "tipo":"Papagaio",
    "nome":"Loro",
    "tags":"Curica"
  },{
    "id":5,
    "tipo":"Cachorro",
    "nome":"Rock",
    "tags":"Pitbull"
    }
  ]
}

And I need to generate a list as follows:

const dados = {
  "Cachorros":[
      {
        "id":1,
        "nome":"Max",
        "tags":"Border Collier"
      },{
        "id":2,
        "nome":"Fini",
        "tags":"Lhasa Apso"
      },{
        "id":5,
        "nome":"Rock",
        "tags":"Pitbull"
      }],
  "Gatos":[{
        "id":3,
        "nome":"Luna",
        "tags":"Siames"
      }],
  "Papagaios":[{
        "id":4,
        "nome":"Loro",
        "tags":"Curica"
     }
  ]
}

What would be the fastest or easiest way to make such a transformation? I’m learning Javascript now and need to handle this data from an API to display it in a table. My logic is still weak, I searched filter, map and reduce methods but could not imagine a way to do it.

Then, could I calculate, for example, how many dogs are there in the new list? And cats and parrots. I imagine this part is the easiest using a length.

3 answers

6

Maybe the way I did it is not the most performative mode, but here I leave an example of how it can be done using Javascript methods like filter(), for in and Object.():

const dados = {"animais":[
  {
    "id":1,
    "tipo":"Cachorro",
    "nome":"Max",
    "tags":"Border Collier"
  },{
    "id":2,
    "tipo":"Cachorro",
    "nome":"Fini",
    "tags":"Lhasa Apso"
  },{
    "id":3,
    "tipo":"Gato",
    "nome":"Luna",
    "tags":"Siames"
  },{
    "id":4,
    "tipo":"Papagaio",
    "nome":"Loro",
    "tags":"Curica"
  },{
    "id":5,
    "tipo":"Cachorro",
    "nome":"Rock",
    "tags":"Pitbull"
    }
  ]
}

let dog = dados.animais.filter(x => x.tipo == 'Cachorro');      // filtra cada tipo de animal
let cat = dados.animais.filter(x => x.tipo == 'Gato');
let parrot = dados.animais.filter(x => x.tipo == 'Papagaio');

let objeto = {                                                 // cria um objeto modelo
  Cachorros: [],
  Gatos: [],
  Papagaios: []
}

Object.assign(objeto.Cachorros, dog);           // transforma o resultado do filter em objeto
Object.assign(objeto.Gatos, cat);
Object.assign(objeto.Papagaios, parrot);

for(let i in objeto.Cachorros) delete objeto.Cachorros[i].tipo;  // retira "tipo" dos objetos
for(let i in objeto.Gatos) delete objeto.Gatos[i].tipo;
for(let i in objeto.Papagaios) delete objeto.Papagaios[i].tipo;

console.log(objeto);
console.log('Quantidade de cachorros: ', objeto.Cachorros.length);
console.log('Quantidade de gatos: ', objeto.Gatos.length);
console.log('Quantidade de papagaios: ', objeto.Papagaios.length);

  • Thank you very much for the reply Andrade. But what if I have a JSON with a huge number of different animal types, there is a way to do without instantiating a Let dog, etc.? For example, using a while or for to traverse the Array.

  • 2

    It was as I commented, depending on the data does not get performatic, I left only as an example even has to do without creating the variables, but, would be more complex. The @Sergio’s answer is perfect,pq, regardless of the amount of items in the arrays and is very lean, although it is more complex for those who are learning, if you have doubts about how much his answer can question it.

6


You can use the reduce to do that:

const animais = dados.animais.reduce((obj, animal) => {
  const tipo = animal.tipo + 's'; 
  const {nome, id, tags} = animal;
  obj[tipo] = (obj[tipo] || []).concat({nome, id, tags});
  return obj;
}, {});

What it does is go through the array of Animais and generate properties with the name of the animal type that are arrays. And add the arrays one by one, reconstructing the structure of these data.

I put it together + 's' to create plurals... but you could simplify using the singular type.

Example:

const dados = {
  "animais": [{
    "id": 1,
    "tipo": "Cachorro",
    "nome": "Max",
    "tags": "Border Collier"
  }, {
    "id": 2,
    "tipo": "Cachorro",
    "nome": "Fini",
    "tags": "Lhasa Apso"
  }, {
    "id": 3,
    "tipo": "Gato",
    "nome": "Luna",
    "tags": "Siames"
  }, {
    "id": 4,
    "tipo": "Papagaio",
    "nome": "Loro",
    "tags": "Curica"
  }, {
    "id": 5,
    "tipo": "Cachorro",
    "nome": "Rock",
    "tags": "Pitbull"
  }]
};

const animais = dados.animais.reduce((obj, animal) => {
  const tipo = animal.tipo + 's'; 
  const {nome, id, tags} = animal;
  obj[tipo] = (obj[tipo] || []).concat({nome, id, tags});
  return obj;
}, {});

console.log(JSON.stringify(animais, null, 2));

In case there are more properties, to become more generic it could be done like this:

const dados = {
  "animais": [{
    "id": 1,
    "tipo": "Cachorro",
    "nome": "Max",
    "tags": "Border Collier"
  }, {
    "id": 2,
    "tipo": "Cachorro",
    "nome": "Fini",
    "tags": "Lhasa Apso"
  }, {
    "id": 3,
    "tipo": "Gato",
    "nome": "Luna",
    "tags": "Siames"
  }, {
    "id": 4,
    "tipo": "Papagaio",
    "nome": "Loro",
    "tags": "Curica"
  }, {
    "id": 5,
    "tipo": "Cachorro",
    "nome": "Rock",
    "tags": "Pitbull"
  }]
};

const ignorar = ['tipo'];

function copiarExcepto(original, excluirProps) {
  return Object.keys(original)
  .filter(prop => !excluirProps.includes(prop)) // excluir as chaves que não interessam
  .reduce((obj, prop) => {
    // adicionar as chaves relevantes ao novo objeto
    return { ...obj,
      [prop]: original[prop]
    }
  }, {});
}

const animais = dados.animais.reduce((obj, animal) => {
  const tipo = animal.tipo + 's'; // criar a chave por tipos
  const novoObjeto = copiarExcepto(animal, ignorar); // copiar o objeto sem as chaves que não queremos
  obj[tipo] = (obj[tipo] || []).concat(novoObjeto); // adicionar o animal à lista
  return obj;
}, {});

console.log(JSON.stringify(animais, null, 2));

  • Wouldn’t it be better to keep all the properties of the object and remove only the type (with Object.assign and delete for example)? This way the solution becomes more generic and does not rule out potential extra properties that objects have.

  • @Isac yes and no, use delete changes the object out of function, creates side effects and difficult to detect bugs. In this case it would be better to have an array with a list of properties not to copy, and use Object.keys to filter before copying the object with the rest N properties. I will add an example of this in the answer.

  • 1

    Could you explain with comments in the code or links what each part of the code does? As the author of the question put in the: I’m learning Javascript now, I think the code itself is quite complex for a beginner not?!

  • 1

    @Leandrade added comments in the second example. If there is a line that you do not know what it does, it says!

  • On my good side, I say by the author of the question, who is a beginner, he can take the code ready and use it, but, would be knowing what is happening behind the code without the comments.

  • 1

    @Leandrade, it is difficult to know. The code is little, but if help is needed I will be here to help the author of the question or others who need :)

  • @Sergio thank you very much for the answer, it was certainly of great value, I will give another study about the map, filter and reduce. Now there is one more question. If I needed to generate an object that contains only arrays with less than 3 animals, how would I do it? Example, there are 3 dogs, but there are 3 cats and 3 parrots, as I would to segregate parrots and cats from dogs generating a new object?

  • @Lucasmorse then you would have to revisit these arrays after they are created and delete the ones that have array.length < 3. You could also do that before you create the property.. But it’s simpler in the end. If you don’t find an answer here on the site that covers this case, ask a new question.

Show 3 more comments

-2

Hello, it’s fine, simple!

const appDiv: HTMLElement = document.getElementById('app');
appDiv.innerHTML = `<h1>TypeScript Starter</h1>`;

const dados = {
  "Cachorros":[
      {
        "id":1,
        "nome":"Max",
        "tags":"Border Collier"
      },{
        "id":2,
        "nome":"Fini",
        "tags":"Lhasa Apso"
      },{
        "id":5,
        "nome":"Rock",
        "tags":"Pitbull"
      }],
  "Gatos":[{
        "id":3,
        "nome":"Luna",
        "tags":"Siames"
      }],
  "Papagaios":[{
        "id":4,
        "nome":"Loro",
        "tags":"Curica"
     }
  ]
}

dados.Cachorros.forEach(myFunction)


function myFunction(value, index, array) {
  appDiv.innerHTML = appDiv.innerHTML + value.nome + "<br>"; 
}

Browser other questions tagged

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