Soma de valores Json

Boa noite pessoal,

Eu tenho esse Array de Json com dois registros, eu preciso somar o valor do atributo “total” de cada um deles. Por exemplo, cada um deles possuem o atributo total, no caso o primeiro registro tem um valor total de 342 e o segundo o valor 417. O que preciso é atribuir a soma de um com o outro em uma variável para que eu possa apresentar a soma na tela.

No caso a minha variável teria o valor igual a 759 (342 + 417).

Segue Json do retorno da API.

[{
            "date": "11/09/2014",
            "visualization": [
              {
                "valueVisualize": "0341",
                "dataRegister": "11/09/2014",
                "intervals": [
                  {
                    "name": "08",
                    "types": [
                      {
                        "name": "Inter-Prestadora",
                        "total": 342
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "date": "12/09/2014",
            "visualization": [
              {
                "valueVisualize": "0341",
                "dataRegister": "12/09/2014",
                "intervals": [
                  {
                    "name": "08",
                    "types": [
                      {
                        "name": "Inter-Prestadora",
                        "total": 417
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]

Uma possível solução seria assim:

const array = [ /* your JSON goes here */ ];

let total = 0;

array.forEach(a =>
  a.visualization.forEach(v =>
    v.intervals.forEach(i =>
      i.types.forEach(t => total += t.total))));

console.log(total);

EDIT: Alterei minha resposta um pouco depois de ver a do @PedreiroDeSoftware porque vi que era desnecessário criar o array totals e depois fazer reduce.

Uma outra forma de resolver é por meio do index de cada objeto:

function calcularTotal(data){
    let total = 0;
    data.forEach(function(inList){
	total+= inList
	.visualization[0]
	.intervals[0]
	.types[0]
	.total;
    });
    return total;
}

alert(calcularTotal(array));

Só um adendo, este tipo de resposta da api é estressante, pois tem que ficar analisando a estrutura do json.

A resposta deveria vir semelhante a uma tabela, tipo assim:

let dataTable =   {
    colsNames: ["date", "valueVisualize","dataRegister", "name","typeName","total"],
    rows:[
        ["11/09/2014", "0341", "11/09/2014", "08", "Inter-Prestadora", 342],
        ["12/09/2014", "0341", "12/09/2014", "08", "Inter-Prestadora", 417]
    ]
}

function somaCustom(data){
    let total = 0;
    data.rows.forEach(function(row){
        total += row[5];
    });
	return total;
}

alert("Soma custom: "+ somaCustom(dataTable));

Creio que esta abordagem é mais eficiente até do que a adoção do YAML.

Até mesmo o reduce fica mais enxuto:

function somaCustom2(data){
    return data.rows.reduce((sum,columnTotal) => sum + columnTotal[5], 0);
}
alert("Soma custom 2: "+somaCustom2(dataTable));

Entretanto, a primeira abordagem é mais comum/simples:

function somaCustom(data){
    let total = 0;
    data.rows.forEach(function(row){ total += row[5];});
    return total;
}

Comparações:

Isso é basicamente uma crítica à forma como os dados estão sendo trafegados via JSON.

1 curtida

@PedreiroDeSoftware entendo que a estrutura do JSON que você propos é mais eficiente para analisar no cliente, mas uma vez me disseram que não é boa prática uma API retornar JSON dessa forma, que o JSON tem que ter significado semântico condizente com o tipo de objeto que está retornando. Que quando você retorna do jeito que você sugeriu ele fica atrelado a uma estrutura de tabela e não poderia ser usado em outros contextos. Voce poderia comentar sobre essas afirmações, por favor?

Com algumas adaptações as duas soluções funcionaram para esse retorno Json que mandei como exemplo …

@PedreiroDeSoftware quanto ao retorno do json da api, é somente isso que recebo, não tenho como alterar, e também a minha grid já está toda estruturada nesse formato de retorno. O meu problema esta sendo apenas a soma dos valores totais.

@PedreiroDeSoftware Depois de realizar mais testes diferentes, encontrei um gap para o foreach por meio do index de cada objeto.

O que acontece é que o retorno Json pode variar de acordo com os dados segue um exemplo.

[
        { 
          "valueVisualize": "08", 
          "types": [ 
            { 
              "name": "Inter-Prestadora", 
              "total": [ 
                { 
                  "total": { 
                    "FTBJANELA": "08        ", 
                    "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                    "FTBJANCIACODCIA": "0121 ", 
                    "FTBJANCIACODCIA_DOA": null, 
                    "FTBJANDATULTENV": null, 
                    "FTBJANQTDEBP": 1, 
                    "FTBJANPARAN": null, 
                    "FTBJANTIPPORT": 0 
                  } 
                }, 
                { 
                  "total": { 
                    "FTBJANELA": "08        ", 
                    "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                    "FTBJANCIACODCIA": null, 
                    "FTBJANCIACODCIA_DOA": "0131 ", 
                    "FTBJANDATULTENV": null, 
                    "FTBJANQTDEBP": 1, 
                    "FTBJANPARAN": null, 
                    "FTBJANTIPPORT": 0 
                  } 
                } 
              ] 
            } 
          ] 
        }, 
        { 
          "valueVisualize": "16", 
          "types": [ 
            { 
              "name": "Inter-Prestadora", 
              "total": [ 
                { 
                  "total": { 
                    "FTBJANELA": "16        ", 
                    "FTBJANDATULTAG": "2009-03-24T19:00:00.000Z", 
                    "FTBJANCIACODCIA": "0121 ", 
                    "FTBJANCIACODCIA_DOA": null, 
                    "FTBJANDATULTENV": null, 
                    "FTBJANQTDEBP": 1, 
                    "FTBJANPARAN": null, 
                    "FTBJANTIPPORT": 0 
                  } 
                }, 
                { 
                  "total": { 
                    "FTBJANELA": "16        ", 
                    "FTBJANDATULTAG": "2009-03-24T19:00:00.000Z", 
                    "FTBJANCIACODCIA": null, 
                    "FTBJANCIACODCIA_DOA": "0131 ", 
                    "FTBJANDATULTENV": null, 
                    "FTBJANQTDEBP": 1, 
                    "FTBJANPARAN": null, 
                    "FTBJANTIPPORT": 0 
                  } 
                } 
              ] 
            } 
          ] 
        } 
      ]

Veja que tenho casos que o meu ‘valueVisualize’ possui mais de um total, nesse caso precisaria ter um ‘total’ de cada ‘visualization’ e depois um total geral da soma de cada visualization …

Conseguem me ajudar?

@wldomiciano, é difícil responder a essa pergunta.
Eu não tenho um argumento que tenha sido objeto de pesquisa, ou outra referência, é uma experiência/observação particular.

Então posso apenas levantar novos questionamentos.

Assim, tomemos como ponto de partida a consulta ao banco de dados.

É uma boa prática trazer mais dados que o necessário em uma consulta para que o objeto persistido seja semanticamente equivalente ao json?

É uma boa prática criar vários DTOs para atender as consultas customizadas?

Ao criar um DTO, não se perde a compatibilidade semântica entre o objeto original e o consultado?

O correto não seria a ferramenta servir ao desenvolvedor e não o desenvolvedor à ferramenta?

Como dito, eu não tenho uma boa argumentação em relação a afirmação realizada, mas tenho perguntas que me levam a questionar se não seria uma má prática enviar objetos emaranhados para o cliente desenrolar.

Quais contextos?

Eu posso levantar a questão da padronização.

Se o cliente e o servidor compreendem a padronização, a comunicação é mais suave.

Isso é interessante pois no presente tópico não existe uma padronização:

Além disso é mais fácil ler e percorrer uma matriz/tabela do que um mapeamento.

Cabe esclarecer que a tabela proposta é parte de uma response composta por mais chaves.

Fiz um mock (58 linhas) de uma consulta mais complexa, cuja saida no Postmam é a seguinte:

{
    "details": {
        "etc": "etc",
        "results": 2
    },
    "table": {
        "colsNames": [
            "id_compra",
            "date",
            "valueVisualize",
            "dataRegister",
            "name",
            "typeName",
            "total",
            {
                "colsNamesComprador": [
                    "id",
                    "nome",
                    "idade",
                    "sexo"
                ]
            }
        ],
        "rows": [
            [
                23423,
                "11/09/2014",
                "0341",
                "11/09/2014",
                "08",
                "Inter-Prestadora",
                342,
                [
                    1,
                    "jose",
                    45,
                    "M"
                ]
            ],
            [
                23478,
                "11/09/2012",
                "0342",
                "11/09/2012",
                "08",
                "Inter-Prestadora",
                349,
                [
                    2,
                    "maria",
                    23,
                    "F"
                ]
            ]
        ]
    },
    "status": "SUCCESS"
}

scripts auxiliares:

function asString(json){
    return JSON.stringify(json);
}
function parseJson(data){
    return JSON.parse(data);
}

function Response(data){
    data = parseJson(data);
    let response = {
        details: data.details,
        status: data.status,
        succes: data.status == "SUCCESS",
        notFound: data.status == "NOT_FOUND",
    }
    if(data.table){
        response.colsNames = data.table.colsNames;
        response.rows = data.table.rows;
    }
    return response;
}

function Comprador(data){
    let comprador = {
        "id": data[0],
        "nome":data[1],
        "idade":data[2],
        "sexo":data[3]
    }
    return comprador;
}

if(responseCode.code >= 200 && responseCode.code <= 299){
    let response = Response(responseBody);
    let rows = response.rows;
    rows.forEach((row) => {
        let comprador = Comprador(row[7]);
        console.log(asString(comprador));
    });
}

Então, a resposta para a utilização em outros contextos é:
depende de como os dados são manipulados.
Por exemplo, a função que extrai os dados do comprador e retorna um JSON.

image

Método que realizava o mock no servidor:

@JSONMapping("/complex")
    public Response complex(){
    	JSONObject details = new JSONObject();
    	details.put("results", 2);
    	details.put("etc", "etc");
    	
    	Response response = Response.success(details);

    	response.setColsNames("id_compra", "date", "valueVisualize", "dataRegister", "name", "typeName", "total",
    			response.subColsNames("colsNamesComprador", "id","nome","idade","sexo")
    			);
    	response.addRow(23423, "11/09/2014", "0341", "11/09/2014", "08", "Inter-Prestadora", 342,
    			response.subRow(1, "jose", 45,"M")
    			);
    	response.addRow(23478, "11/09/2012", "0342", "11/09/2012", "08", "Inter-Prestadora", 349,
    			response.subRow(2, "maria", 23,"F")
    			);
    	
    	return response.pack();
    	
    }

Há alguns princípios mas o espaço não seria conveniente, mas no geral é só isso mesmo, a adoção de uma arquitetura.

Não vai servir neste caso, pois:

Embora as chaves tenham o mesmo nome são objetos distintos.
A melhor abordagem é a do @wldomiciano que faz uma varredura.

@VictorSalles, a solução é relativamente simples, mas qual é a chave que tem que ser somada aqui:

"total": { 
                    "FTBJANELA": "08        ", 
                    "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                    "FTBJANCIACODCIA": "0121 ", 
                    "FTBJANCIACODCIA_DOA": null, 
                    "FTBJANDATULTENV": null, 
                    "FTBJANQTDEBP": 1, 
                    "FTBJANPARAN": null, 
                    "FTBJANTIPPORT": 0 
                  } 

@PedreiroDeSoftware Percebi que a minha pergunta ficou um pouco confusa, mas a principio notei que você tenha entendido…

@VictorSalles, a solução é relativamente simples, mas qual é a chave que tem que ser somada aqui:

A chave seria essa: FTBJANQTDEBP.

Neste caso, acredito que daria assim:

const array = [
  {
    date: "11/09/2014",
    visualization: [
      {
        valueVisualize: "0341",
        dataRegister: "11/09/2014",
        intervals: [
          {
            name: "08",
            types: [
              {
                name: "Inter-Prestadora",
                total: [
                  {
                    total: {
                      FTBJANELA: "16        ",
                      FTBJANDATULTAG: "2009-03-24T19:00:00.000Z",
                      FTBJANCIACODCIA: "0121 ",
                      FTBJANCIACODCIA_DOA: null,
                      FTBJANDATULTENV: null,
                      FTBJANQTDEBP: 1,
                      FTBJANPARAN: null,
                      FTBJANTIPPORT: 0
                    }
                  },
                  {
                    total: {
                      FTBJANELA: "16        ",
                      FTBJANDATULTAG: "2009-03-24T19:00:00.000Z",
                      FTBJANCIACODCIA: null,
                      FTBJANCIACODCIA_DOA: "0131 ",
                      FTBJANDATULTENV: null,
                      FTBJANQTDEBP: 1,
                      FTBJANPARAN: null,
                      FTBJANTIPPORT: 0
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  {
    date: "12/09/2014",
    visualization: [
      {
        valueVisualize: "0341",
        dataRegister: "12/09/2014",
        intervals: [
          {
            name: "08",
            types: [
              {
                name: "Inter-Prestadora",
                total: [
                  {
                    total: {
                      FTBJANELA: "16        ",
                      FTBJANDATULTAG: "2009-03-24T19:00:00.000Z",
                      FTBJANCIACODCIA: "0121 ",
                      FTBJANCIACODCIA_DOA: null,
                      FTBJANDATULTENV: null,
                      FTBJANQTDEBP: 1,
                      FTBJANPARAN: null,
                      FTBJANTIPPORT: 0
                    }
                  },
                  {
                    total: {
                      FTBJANELA: "16        ",
                      FTBJANDATULTAG: "2009-03-24T19:00:00.000Z",
                      FTBJANCIACODCIA: null,
                      FTBJANCIACODCIA_DOA: "0131 ",
                      FTBJANDATULTENV: null,
                      FTBJANQTDEBP: 1,
                      FTBJANPARAN: null,
                      FTBJANTIPPORT: 0
                    }
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
];

let total = 0;

array.forEach(a =>
  a.visualization.forEach(v =>
    v.intervals.forEach(i =>
      i.types.forEach(t => {
        total += t.total.reduce((acc, i) => acc + i.total.FTBJANQTDEBP, 0);
      })
    )
  )
);

console.log(total);

@PedreiroDeSoftware Obrigado pela resposta. Eu também não tenho argumentos porque como foi uma pessoa mais experiente que eu, eu não questionei, mas obrigado pela explicação, vou levar em conta das proximas vezes.

1 curtida

Esse mock leva em consideração as variações da key total: numero, array, ou json.

let arrayVariation = [{
  "date": "11/09/2014",
  "visualization": [
    {
      "valueVisualize": "0341",
      "dataRegister": "11/09/2014",
      "intervals": [
        {
          "name": "08",
          "types": [
            {
              "name": "Inter-Prestadora",
              "total": 342
            }
          ]
        }
      ]
    }
  ]
},
{
  "date": "12/09/2014",
  "visualization": [
    {
      "valueVisualize": "0341",
      "dataRegister": "12/09/2014",
      "intervals": [
        {
          "name": "08",
          "types": [
            {
              "name": "Inter-Prestadora",
              "total": 417
            }
          ]
        }
      ]
    }
  ]
},
{
  "date": "12/09/2014",
  "visualization": [
    {
      "valueVisualize": "0341",
      "dataRegister": "12/09/2014",
      "intervals": [
        {
          "name": "08",
          "types": [
            {
              "name": "Inter-Prestadora",
              "total": [ 
                 { 
                   "total": { 
                     "FTBJANELA": "08        ", 
                     "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                     "FTBJANCIACODCIA": "0121 ", 
                     "FTBJANCIACODCIA_DOA": null, 
                     "FTBJANDATULTENV": null, 
                     "FTBJANQTDEBP": 1, 
                     "FTBJANPARAN": null, 
                     "FTBJANTIPPORT": 0 
                   } 
                 }, 
                 { 
                   "total": { 
                     "FTBJANELA": "08        ", 
                     "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                     "FTBJANCIACODCIA": null, 
                     "FTBJANCIACODCIA_DOA": "0131 ", 
                     "FTBJANDATULTENV": null, 
                     "FTBJANQTDEBP": 2, 
                     "FTBJANPARAN": null, 
                     "FTBJANTIPPORT": 0 
                   } 
                 } 
               ] 
             }
           ]
         }
       ]
     }
   ]
 },
 {
   "date": "12/09/2014",
   "visualization": [
     {
       "valueVisualize": "0341",            
       "dataRegister": "12/09/2014",
       "intervals": [
         {
            "name": "08",
            "types": [
              {
                 "name": "Inter-Prestadora",
                  "total": [ 
                     { 
                       "total": { 
                          "FTBJANELA": "08        ", 
                          "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                          "FTBJANCIACODCIA": "0121 ", 
                          "FTBJANCIACODCIA_DOA": null, 
                          "FTBJANDATULTENV": null, 
                          "FTBJANQTDEBP": 3, 
                          "FTBJANPARAN": null, 
                          "FTBJANTIPPORT": 0 
                        } 
                      }, 
                      { 
                        "total": { 
                        "FTBJANELA": "08        ", 
                        "FTBJANDATULTAG": "2009-03-24T11:00:00.000Z", 
                        "FTBJANCIACODCIA": null, 
                        "FTBJANCIACODCIA_DOA": "0131 ", 
                        "FTBJANDATULTENV": null, 
                        "FTBJANQTDEBP": 4, 
                        "FTBJANPARAN": null, 
                        "FTBJANTIPPORT": 0 
                      } 
                    } 
                  ] 
                }
              ]
            }
          ]
        }
      ]
    }		  
  ];

  function calcularTotalComVariacao(data){
    let total = 0;
    data.forEach(result =>
      result.visualization.forEach(visualize =>
        visualize.intervals.forEach(interval =>
          interval.types.forEach(type => 
            {
              let totalVariante = type.total;
              if(Array.isArray(totalVariante)){
                totalVariante.forEach(result => total += result.total.FTBJANQTDEBP);
              }else{
                total += totalVariante;
              }
            }
          )
        )
      )
    );
	  return total;
    }

  console.log(">> : >> "+calcularTotalComVariacao(arrayVariation));