Desserializando um JSON em um objeto JavaScript

266

Eu tenho uma sequência em um aplicativo de servidor Java que é acessado usando AJAX. Parece algo como o seguinte:

var json = [{
    "adjacencies": [
        {
          "nodeTo": "graphnode2",
          "nodeFrom": "graphnode1",
          "data": {
            "$color": "#557EAA"
          }
        }
    ],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode1",
    "name": "graphnode1"
},{
    "adjacencies": [],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode2",
    "name": "graphnode2"
}];

Quando a string é retirada do servidor, existe uma maneira fácil de transformar isso em um objeto JavaScript (ou matriz) ativo? Ou tenho que dividir manualmente a string e criar meu objeto manualmente?

mj_
fonte
possível duplicata de como analisar JSON em javascript
Felix Kling
Possível duplicata do Parse JSON em JavaScript?
M9a

Respostas:

397

Suporte para navegadores modernos JSON.parse().

var arr_from_json = JSON.parse( json_string );

Nos navegadores que não usam, você pode incluir a json2biblioteca .

user113716
fonte
Como isso funcionará para os campos de data no JSON, por exemplo {StartDate: "\ / Date (1372575600000) \ /"}?
Philipp Munin
@PhilippMunin, você pode usar esta função Date da API javascript: new Date (parseInt ("/ Date (946681200000) /". Replace ('/ Date (', '')));
Leo
ou objetos Map () etc, como você faz a desserialização adequada
Ewan
25

O ponto principal do JSON é que as seqüências JSON podem ser convertidas em objetos nativos sem fazer nada. Verifique este link

Você pode usar eval(string)ou JSON.parse(string).

No entanto, evalé arriscado. Em json.org:

A função eval é muito rápida. No entanto, ele pode compilar e executar qualquer programa JavaScript, para que haja problemas de segurança. O uso de avaliação é indicado quando a fonte é confiável e competente. É muito mais seguro usar um analisador JSON. Em aplicativos da Web sobre XMLHttpRequest, a comunicação é permitida apenas para a mesma origem que fornece essa página, portanto, é confiável. Mas pode não ser competente. Se o servidor não for rigoroso em sua codificação JSON ou se não validar escrupulosamente todas as suas entradas, ele poderá fornecer texto JSON inválido que pode estar carregando um script perigoso. A função eval executaria o script, liberando sua malícia.

Abhinav
fonte
1
Eu não entendo o risco. Alguém não pode usar um depurador js para injetar e executar qualquer script que eles desejem?
Xr280xr 28/10
3
@ xr280xr Sim, mas isso acontece apenas localmente no navegador, nem todos os navegadores que baixam o site.
Masterxilo 11/11
16

Faça como o jQuery! (a essência)

function parseJSON(data) {
    return window.JSON && window.JSON.parse ? window.JSON.parse( data ) : (new Function("return " + data))(); 
}
// testing
obj = parseJSON('{"name":"John"}');
alert(obj.name);

Dessa forma, você não precisa de nenhuma biblioteca externa e ainda funciona em navegadores antigos.

Ravan Scafi
fonte
7
Parece que está voltando ao equivalente a eval().
Larsh
1
Isso é perigoso, eval é mau!
Caesarsol
8

Para coletar todos os itens de uma matriz e retornar um objeto json

collectData: function (arrayElements) {

        var main = [];

        for (var i = 0; i < arrayElements.length; i++) {
            var data = {};
            this.e = arrayElements[i];            
            data.text = arrayElements[i].text;
            data.val = arrayElements[i].value;
            main[i] = data;
        }
        return main;
    },

Para analisar os mesmos dados pelos quais passamos assim

dummyParse: function (json) {       
        var o = JSON.parse(json); //conerted the string into JSON object        
        $.each(o, function () {
            inner = this;
            $.each(inner, function (index) {
                alert(this.text)
            });
        });

}
Tarun Gupta
fonte
4

Você também pode usar, eval()mas JSON.parse()é a maneira mais segura e fácil, então por que você usaria?

bom e funciona

var yourJsonObject = JSON.parse(json_as_text);

Não vejo nenhuma razão para você preferir usar eval. Isso apenas coloca seu aplicativo em risco.

Dito isto - isso também é possível.

ruim - mas também funciona

var yourJsonObject = eval(json_as_text);

Por que é evaluma má ideia?

Considere o seguinte exemplo.

Alguns terceiros ou usuários forneceram dados da string JSON.

var json = `
[{
    "adjacencies": [
        {
          "nodeTo": function(){
            return "delete server files - you have been hacked!";
          }(),
          "nodeFrom": "graphnode1",
          "data": {
            "$color": "#557EAA"
          }
        }
    ],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode1",
    "name": "graphnode1"
},{
    "adjacencies": [],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode2",
    "name": "graphnode2"
}]
`;

Seu script do lado do servidor processa esses dados.

Usando JSON.parse:

window.onload = function(){
  var placeholder = document.getElementById('placeholder1');
  placeholder.innerHTML = JSON.parse(json)[0].adjacencies[0].nodeTo;
}

jogará:

Uncaught SyntaxError: Unexpected token u in JSON at position X. 

A função não será executada.

Você está seguro.

Usando eval():

window.onload = function(){
  var placeholder = document.getElementById('placeholder1');
  placeholder.innerHTML = eval(json)[0].adjacencies[0].nodeTo;
}

executará a função e retornará o texto.

Se eu substituir essa função inofensiva por uma que remova arquivos da pasta do site, você foi invadido. Nenhum erro / aviso será lançado neste exemplo.

Você não está seguro.

Consegui manipular uma sequência de texto JSON para que ela funcione como uma função que será executada no servidor.

eval(JSON)[0].adjacencies[0].nodeTo espera processar uma string JSON, mas, na realidade, acabamos de executar uma função em nosso servidor.

Isso também pode ser evitado se verificarmos no servidor todos os dados fornecidos pelo usuário antes de passá-los para uma eval()função, mas por que não usar a ferramenta integrada para analisar o JSON e evitar todo esse problema e perigo?

DevWL
fonte
1

E se você também deseja que o objeto desserializado tenha funções, use minha pequena ferramenta: https://github.com/khayll/jsmix

//first you'll need to define your model
var GraphNode = function() {};
GraphNode.prototype.getType = function() {
   return this.$type;
}

var Adjacency = function() {};
Adjacency.prototype.getData =n function() {
    return this.data;
}

//then you could say:
var result = JSMix(jsonData)
    .withObject(GraphNode.prototype, "*")
    .withObject(Adjacency.prototype, "*.adjacencies")
    .build();

//and use them
console.log(result[1][0].getData());
fishgen
fonte
0

Se você colar a string no lado do servidor no html, não precisará fazer nada:

Para java simples em jsp:

var jsonObj=<%=jsonStringInJavaServlet%>;

Para suportes de largura jsp:

var jsonObj=<s:property value="jsonStringInJavaServlet" escape="false" escapeHtml="false"/>;
surfealokesea
fonte