Deserializowanie JSON w obiekt JavaScript

266

Mam ciąg w aplikacji serwera Java, do której można uzyskać dostęp za pomocą AJAX. Wygląda mniej więcej tak:

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"
}];

Czy po wyciągnięciu łańcucha z serwera istnieje prosty sposób, aby przekształcić go w żywy obiekt JavaScript (lub tablicę)? Czy też muszę ręcznie podzielić ciąg i ręcznie zbudować obiekt?

mj_
źródło
możliwy duplikat sposobu parsowania Jsona w javascript
Felix Kling
Możliwy duplikat parsowania JSON w JavaScript?
m93a

Odpowiedzi:

397

Obsługa nowoczesnych przeglądarek JSON.parse().

var arr_from_json = JSON.parse( json_string );

W przeglądarkach, które nie można dołączyć do json2biblioteki .

użytkownik113716
źródło
Jak to będzie działać dla pól daty w JSON, na przykład {StartDate: "\ / Date (1372575600000) \ /"}?
Philipp Munin
@ PhilippMunin można użyć tej funkcji Data z interfejsu API javascript: nowa data (parseInt ("/ Date (946681200000) /". Replace ('/ Date (', '')));
Leo
lub obiekty Map () itp., w jaki sposób przeprowadzacie prawidłową deserializację
Ewan
25

Cały sens JSON polega na tym, że ciągi JSON można konwertować na obiekty rodzime bez robienia czegokolwiek. Sprawdź ten link

Można użyć jednej eval(string)lub JSON.parse(string).

Jest to jednak evalryzykowne. Z json.org:

Funkcja eval jest bardzo szybka. Może jednak kompilować i uruchamiać dowolny program JavaScript, więc mogą wystąpić problemy z bezpieczeństwem. Zastosowanie eval jest wskazane, gdy źródło jest zaufane i kompetentne. O wiele bezpieczniej jest używać analizatora składni JSON. W aplikacjach internetowych za pośrednictwem XMLHttpRequest komunikacja jest dozwolona tylko do tego samego źródła, które udostępnia tę stronę, więc jest zaufana. Ale może nie być kompetentny. Jeśli serwer nie jest rygorystyczny w kodowaniu JSON lub nie skrupulatnie sprawdza poprawność wszystkich swoich danych wejściowych, może dostarczyć niepoprawny tekst JSON, który może zawierać niebezpieczny skrypt. Funkcja eval wykonałaby skrypt, wyzwalając jego złośliwość.

Abhinav
źródło
1
Nie rozumiem ryzyka. Czy i tak nikt nie może użyć debugera js do wstrzyknięcia i wykonania dowolnego skryptu?
xr280xr
3
@ xr280xr Tak, ale dzieje się tak tylko lokalnie w ich przeglądarce, a nie w każdej przeglądarce, która pobiera witrynę.
masterxilo
16

Rób jak jQuery! (esencja)

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);

W ten sposób nie potrzebujesz żadnej zewnętrznej biblioteki i nadal działa ona na starych przeglądarkach.

Ravan Scafi
źródło
7
Wygląda na to, że spada do odpowiednika eval().
LarsH
1
To niebezpieczne, eval jest złe!
caesarsol
8

Aby zebrać wszystkie elementy tablicy i zwrócić obiekt 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;
    },

Aby przeanalizować te same dane, przez które przechodzimy w ten sposób

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
źródło
4

Możesz również użyć, eval()ale JSON.parse()jest to bezpieczniejszy i łatwiejszy sposób, więc dlaczego miałbyś?

dobrze i działa

var yourJsonObject = JSON.parse(json_as_text);

Nie widzę żadnego powodu, dla którego wolałbyś skorzystać eval. To tylko zagraża twojej aplikacji.

To powiedziawszy - jest to również możliwe.

źle - ale też działa

var yourJsonObject = eval(json_as_text);

Dlaczego jest evalto zły pomysł?

Rozważ następujący przykład.

Niektóre strony trzecie lub użytkownik podali dane ciągu 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"
}]
`;

Skrypt po stronie serwera przetwarza te dane.

Używanie JSON.parse:

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

rzuci:

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

Funkcja nie zostanie wykonana.

Jesteś bezpieczny.

Używanie eval():

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

wykona funkcję i zwróci tekst.

Jeśli zamienię tę nieszkodliwą funkcję na tę, która usuwa pliki z folderu witryny, zostałeś zhakowany. W tym przykładzie nie zostaną zgłoszone żadne błędy / ostrzeżenia.

NIE jesteś bezpieczny.

Byłem w stanie manipulować ciągiem tekstowym JSON, więc działa on jako funkcja, która zostanie wykonana na serwerze.

eval(JSON)[0].adjacencies[0].nodeTo oczekuje przetworzenia ciągu JSON, ale w rzeczywistości właśnie wykonaliśmy funkcję na naszym serwerze.

Można temu zapobiec, jeśli po stronie serwera sprawdzimy wszystkie dane dostarczone przez użytkownika przed przekazaniem ich do eval()funkcji, ale dlaczego nie skorzystać z wbudowanego narzędzia do analizy JSON i uniknąć wszystkich problemów i niebezpieczeństw?

DevWL
źródło
1

A jeśli chcesz, aby zdejrializowany obiekt miał również funkcje, możesz użyć mojego małego narzędzia: 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
źródło
0

Jeśli wkleisz ciąg po stronie serwera do html, nie musisz nic robić:

Dla zwykłego języka Java w jsp:

var jsonObj=<%=jsonStringInJavaServlet%>;

Dla rozpórek szerokości jsp:

var jsonObj=<s:property value="jsonStringInJavaServlet" escape="false" escapeHtml="false"/>;
surfealokesea
źródło