Bezpiecznie zamienia ciąg JSON w obiekt

1334

Biorąc pod uwagę ciąg danych JSON, jak mogę bezpiecznie przekształcić ten ciąg w obiekt JavaScript?

Oczywiście mogę to zrobić niepewnie za pomocą czegoś takiego:

var obj = eval("(" + json + ')');

ale to sprawia, że ​​jestem podatny na ciąg JSON zawierający inny kod, którego ewolucję wydaje się bardzo niebezpieczna.

Matt Sheppard
źródło
77
W większości języków eval niesie dodatkowe ryzyko. Eval pozostawia otwarte drzwi do wykorzystania przez hakerów. JEDNAK pamiętaj, że wszystkie javascript działają na kliencie. OCZEKIWAJ , że zostaną zmienione przez hakerów. Mogą EVALOWAĆ wszystko, co chcą, tylko za pomocą konsoli. Musisz zbudować ochronę po stronie serwera.
Beachhouse
19
Ok, teraz jest 2014 i nigdy nie powinieneś używać go evaldo analizowania ciągu JSON, ponieważ wystawiałbyś swój kod na „wstrzyknięcie kodu”. Użyj JSON.parse(yourString)zamiast tego.
Daniel
Czy dane JSON są dosłowne?
shanechiu
@shanechiu: jeśli masz na myśli skalarny typ danych, to tak. Jest tylko ciągiem ze składnią klucz-wartość.
0zkr PM

Odpowiedzi:

1960

JSON.parse(jsonString) jest czystym podejściem JavaScript, o ile możesz zagwarantować dość nowoczesną przeglądarkę.

Jonathan.
źródło
74
Jestem prawie pewien, że jest to bezpieczne dla Node.js
Stephen
76
@ vsync zdajesz sobie sprawę, że jest to TYLKO czysta odpowiedź JavaScript ... jeśli przeczytasz opis znacznika javascript, zobaczysz to ... ” O ile nie jest zawarty tag dla środowiska / biblioteki, odpowiedź czystego JavaScript jest oczekiwano. ".. Daję +1 za to, że jestem jedyną odpowiedzią na javascript ...
iConnor
12
Jeśli wykonujesz NodeJS, nie ma sposobu, żebym załadował jQuery tylko po to, aby parsować jsonString w obiekcie JSON. Dlatego głosuj za odpowiedzią Jonathana
Antoniego
6
Według tego linku jest obsługiwany przez IE8 +, chociaż mówi:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid
878

Metoda jQuery jest teraz przestarzała. Zamiast tego użyj tej metody:

let jsonObject = JSON.parse(jsonString);

Oryginalna odpowiedź przy użyciu przestarzałej funkcji jQuery :

Jeśli używasz jQuery, po prostu użyj:

jQuery.parseJSON( jsonString );

Właśnie tego szukasz (zobacz dokumentację jQuery ).

Alex V.
źródło
7
Czy istnieje powód, aby używać tego zamiast JSON.parse ()?
Jon
8
jQuery.parseJSONdomyślnie używa, JSON.parsejeśli istnieje, więc jedynym powodem, aby użyć tego w porównaniu z rzeczywistym, jest to, że potrzebujesz rezerwy dla <IE7. Zostało to zmienione w jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren
9
Aktualizacja 2016: Od wersji jQuery 3.0 wartość $ .parseJSON jest przestarzała i zamiast tego należy użyć rodzimej metody JSON.parse.
jkdev
159

Ta odpowiedź dotyczy IE <7, w przypadku współczesnych przeglądarek sprawdź odpowiedź Jonathana powyżej.

Ta odpowiedź jest nieaktualna, a odpowiedź Jonathana powyżej ( JSON.parse(jsonString)) jest teraz najlepszą odpowiedzią .

JSON.org ma parsery JSON dla wielu języków, w tym czterech różnych dla JavaScript. Wierzę, że większość ludzi uważa json2.js za implementację goto.

Jan
źródło
24
Chciałbym, żeby ludzie przestali głosować za odpowiedzią. Był dokładny, kiedy został opublikowany w 2008 roku. Po prostu głosuj na nowy.
John
22
Jeśli odpowiedź jest teraz nieaktualna, rozważ ją zaktualizowanie.
Sotirios Delimanolis,
2
dla IE <8 musisz tego użyć.
Mahmoodvcs,
74

Skorzystaj z prostego przykładu kodu w „ JSON.parse () ”:

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

i odwrócenie:

var str = JSON.stringify(arr);
Ronald
źródło
23

Nie jestem pewien, czy można to zrobić inaczej, ale oto jak to zrobić w Prototypie (samouczek JSON) .

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

Wywołanie evalJSON()z wartością true, ponieważ argument dezynfekuje przychodzący ciąg.

Mark Biek
źródło
22

To wydaje się być problemem:

Dane wejściowe, które są odbierane przez Ajax websocket itp., I będą w formacie String, ale musisz wiedzieć, czy tak JSON.parsable. Najważniejsze jest to, że jeśli zawsze go uruchomisz JSON.parse, program MOŻE kontynuować „z powodzeniem”, ale nadal zobaczysz błąd zgłaszany do konsoli z przerażeniem "Error: unexpected token 'x'".

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});
Cody
źródło
NIE. Problem polega na tym, że oczekujesz obiektu JSON i możesz skończyć z (function(){ postCookiesToHostileServer(); }());jeszcze bardziej nieprzyjemnymi rzeczami w kontekście Node.
Yaur
Cóż, JSON.parse przeszukuje dane wejściowe funkcji (co w tym przypadku nie pomogłoby, ponieważ jest to obiekt IIF ->). Wydaje się, że najlepszym sposobem na zajęcie się tym tematem jest próba złapania. (Patrz edycja)
Cody
18

Jeśli używasz jQuery , możesz także użyć:

$.getJSON(url, function(data) { });

Następnie możesz robić takie rzeczy jak

data.key1.something
data.key1.something_else

itp.

Leanan
źródło
używasz jQuery, prawda?
Alexandre C.
15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

Oddzwanianie jest przekazywane zwracane dane, które będą obiektem JavaScript lub tablicą zdefiniowaną przez strukturę JSON i analizowane przy użyciu $.parseJSON()metody.

Prahlad
źródło
12

Dla zabawy, oto sposób korzystania z funkcji:

 jsonObject = (new Function('return ' + jsonFormatData))()
lessisawesome
źródło
1
Ciekawe podejście, nie jestem pewien, czy użyłbym tego z JSON.Parse, ale miło jest widzieć, że ktoś myśli nieszablonowo.
5
Jest to bardzo podobne do zwykłego korzystania evalz niego i nie jest bezpieczne. : P
Florrie,
7
Ma to wszystkie wady użytkowania, evalale jest bardziej skomplikowane i trudniejsze do zrozumienia dla opiekunów.
Quentin
9

Korzystanie JSON.parsejest prawdopodobnie najlepszym sposobem.

Oto przykład demo na żywo .

var jsonRes = '{ "students" : [' +
          '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +
          '{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +
          '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';
var studentObject = JSON.parse(jsonRes);
Bharath Kumaar
źródło
9

Najłatwiejszy sposób przy użyciu parse()metody:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

Następnie możesz uzyskać wartości elementów JSON, na przykład:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

Korzystanie z jQuery zgodnie z opisem w jQuery.parseJSON()dokumentacji:

JSON.parse(jsonString);
Jorgesys
źródło
9

Spróbuj użyć metody z tym obiektem Data. ex: Data='{result:true,count:1}'

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

Ta metoda naprawdę pomaga w Nodejs, gdy pracujesz z programowaniem portu szeregowego

GPrathap
źródło
To naprawdę zabawne, jak ludzie są przywiązani do „eval is evil” i zrobią wszystko, aby tego uniknąć, nawet
przepisując
Czy zgoda ta sztuczka jest bezpieczną metodą przekształcania łańcucha w obiekt JSON? Mógłbym użyć tego, ponieważ nie są potrzebne żadne dodatkowe importy js.
Ktoś
1
DOWOLNE podejście wykorzystujące evallub Functionjest równie wrażliwe
Slai
undefined; function bye() {...} bye();
Salvioner
5

Znalazłem „lepszy” sposób:

W CoffeeScript:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

W JavaScript:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});
dorycki
źródło
4

Parsowanie JSON jest zawsze bólem. Jeśli dane wejściowe nie są zgodne z oczekiwaniami, generuje błąd i psuje to, co robisz.

Możesz użyć poniższej małej funkcji, aby bezpiecznie przeanalizować dane wejściowe. Zawsze obraca obiekt, nawet jeśli dane wejściowe są niepoprawne lub są już obiektami, które są lepsze w większości przypadków:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};
Tahsin Turkoz
źródło
Object.prototype.toString.call(input) === '[object Object]'powinien być typeof input === 'object'IMO
Serge K.
typeof input zwraca obiekt również dla null i tablic. Nie jest to więc bezpieczny sposób.
Tahsin Turkoz
Już wcześniej zajmowałeś się tą nullsprawą, a tablica jest obiektem . Jeśli chcesz to przetestować, możesz użyć instanceof. Ponadto, jeśli dasz tej funkcji an Array, złapie się i return defkiedy zwróci idealnie idealną tablicę.
Serge K.
Mój komentarz dotyczył zdrowego rozsądku podczas łapania przedmiotów. Moja funkcja może mieć kilka prewencji, ale użycie metody typeof nie jest ogólnie preferowanym sposobem wykrywania obiektów.
Tahsin Turkoz
IMO, zdrowy rozsądek nie używa toString()metody sprawdzania, czy zmienna jest obiektem, czy nie. Zobacz AngularJS , jQuery , Underscore , a nawet devs
Serge K.
3
JSON.parse(jsonString);

json.parse zmieni się w obiekt.

Shekhar Tyagi
źródło
3

Jeśli mamy taki ciąg:

"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"

możemy po prostu użyć JSON.parsedwukrotnie, aby przekonwertować ten ciąg na obiekt JSON:

var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
var jsonString= JSON.parse(sampleString)
var jsonObject= JSON.parse(jsonString)

Możemy wyodrębnić wartości z obiektu JSON, używając:

// instead of last JSON.parse:
var { status, token } = JSON.parse(jsonString);

Wynik będzie:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059
Hamid Araghi
źródło
3

JSON.parse() konwertuje dowolny ciąg JSON przekazany do funkcji na obiekt JSON.

Aby to lepiej zrozumieć, naciśnij, F12aby otworzyć „Inspect Element” w przeglądarce i przejdź do konsoli, aby napisać następujące polecenia:

var response = '{"result":true,"count":1}'; //sample json object(string form)
JSON.parse(response); //converts passed string to JSON Object.

Teraz uruchom polecenie:

console.log(JSON.parse(response));

Otrzymasz wynik jako obiekt {result: true, count: 1}.

Aby użyć tego obiektu, możesz przypisać go do zmiennej, może obj:

var obj = JSON.parse(response);

Za pomocą operatora obji (kropka .) można uzyskać dostęp do właściwości obiektu JSON.

Spróbuj uruchomić polecenie:

console.log(obj.result);
Pushkar Kathuria
źródło
3

Oficjalna dokumentacja :

JSON.parse()Metoda analizuje ciąg JSON, konstruowanie wartości JavaScript lub obiekt opisany przez ciąg. reviverMożna zapewnić opcjonalną funkcję do przeprowadzenia transformacji obiektu wynikowego przed jego zwróceniem.

Składnia:

JSON.parse(text[, reviver])

Parametry:

text : Ciąg do analizy jako JSON. Zobacz obiekt JSON, aby uzyskać opis składni JSON.

reviver (optional) : Jeśli funkcja, określa, w jaki sposób wartość pierwotnie wygenerowana przez parsowanie jest przekształcana przed zwróceniem.

Zwracana wartość

Obiekt odpowiadający podanemu tekstowi JSON.

Wyjątki

Zgłasza wyjątek SyntaxError, jeśli analizowany ciąg nie jest prawidłowym kodem JSON.

Salomon Zhang
źródło
2

Konwersja obiektu na JSON, a następnie jego parsowanie działa dla mnie jak:

JSON.parse(JSON.stringify(object))
Liuver Reynier Durán Pérez
źródło
1
Przegapiłeś nawias zamykający.
Salomon Zhang,
2

Analizując ciąg JSON JSON.parse(), dane stają się obiektem JavaScript:

JSON.parse(jsonString)

Tutaj JSON reprezentuje przetwarzanie zestawu danych JSON.

Wyobraź sobie, że otrzymaliśmy ten tekst z serwera internetowego:

'{ "name":"John", "age":30, "city":"New York"}'

Aby przeanalizować w obiekcie JSON:

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}'); 

Oto objodpowiedni obiekt JSON, który wygląda:

{ "name":"John", "age":30, "city":"New York"}

Aby pobrać wartość, użyj .operatora:

obj.name // John
obj.age //30

Konwertuj obiekt JavaScript na ciąg znaków za pomocą JSON.stringify().

Amitesh
źródło
1

Wystarczy przeanalizować okładkę dla różnych typów danych wejściowych

Analizuj dane za pomocą JSON.parse (), a dane stają się obiektem JavaScript.

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

Podczas korzystania z JSON.parse () na JSON pochodzącym z tablicy metoda zwróci tablicę JavaScript zamiast obiektu JavaScript.

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

Obiekty daty nie są dozwolone w JSON. Bo Daty robią coś takiego

var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';
var obj = JSON.parse(text);
obj.birth = new Date(obj.birth);

Funkcje nie są dozwolone w JSON. Jeśli potrzebujesz dołączyć funkcję, napisz ją jako ciąg.

var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");
Małpa
źródło
0

Starsze pytanie, wiem, jednak nikt nie zauważa tego rozwiązania za pomocą new Function()anonimowej funkcji zwracającej dane.


Tylko przykład:

 var oData = 'test1:"This is my object",test2:"This is my object"';

 if( typeof oData !== 'object' )
  try {
   oData = (new Function('return {'+oData+'};'))();
  }
  catch(e) { oData=false; }

 if( typeof oData !== 'object' )
  { alert( 'Error in code' ); }
 else {
        alert( oData.test1 );
        alert( oData.test2 );
      }

Jest to trochę bardziej bezpieczne, ponieważ wykonuje się wewnątrz funkcji i nie kompiluje bezpośrednio w kodzie. Jeśli więc wewnątrz znajduje się deklaracja funkcji, nie będzie ona powiązana z domyślnym obiektem okna.

Używam tego do łatwego i szybkiego „kompilowania” ustawień konfiguracji elementów DOM (na przykład atrybutu danych).

Codebeat
źródło
0

Podsumowanie:

JavaScript (zarówno przeglądarka, jak i NodeJS) mają wbudowany JSONobiekt. Na tym obiekcie są 2 wygodne metody radzenia sobie JSON. Są to:

  1. JSON.parse() Bierze JSONjako argument, zwraca obiekt JS
  2. JSON.stringify() Pobiera obiekt JS jako argument zwracający JSONobiekt

Inne aplikacje:

Poza tym bardzo wygodnie sobie z JSONnimi radzą można je wykorzystać na inne sposoby. Połączenie obu JSONmetod pozwala nam bardzo łatwo tworzyć głębokie klony tablic lub obiektów. Na przykład:

let arr1 = [1, 2, [3 ,4]];
let newArr = arr1.slice();

arr1[2][0] = 'changed'; 
console.log(newArr); // not a deep clone

let arr2 = [1, 2, [3 ,4]];
let newArrDeepclone = JSON.parse(JSON.stringify(arr2));

arr2[2][0] = 'changed'; 
console.log(newArrDeepclone); // A deep clone, values unchanged

Willem van der Veen
źródło
0

Możesz także użyć reviverfunkcji do filtrowania.

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

Aby uzyskać więcej informacji przeczytaj JSON.parse.

Durgpal Singh
źródło
0

JSON.parse to właściwy sposób na konwersję łańcucha na obiekt, ale jeśli analizowany ciąg nie jest obiektem lub łańcuch nie jest poprawny, wygeneruje błąd, który spowoduje przerwanie reszty kodu, więc jest idealny do zawijania funkcji JSON.parse w try-catch like

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}
Deepak Thomas
źródło
-1

Spróbuj tego. Ten jest napisany na maszynie.

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }
Supun Dharmarathne
źródło
Jestem nowy w maszynopisie. Do czego to dodaje JSON.parse()?
Marc L.,
Jeśli wystąpi jakiś wyjątek, zwróci on sam łańcuch wejściowy
Supun Dharmarathne
-1
/**
 * Safely turning a JSON string into an object
 *
 * @param {String} str - JSON String
 * @returns deserialized object, false if error
 */
export function jsonParse(str) {
  let data = null;
  try {
    data = JSON.parse(str);
  } catch (err) {
    return false;
  }
  return data;
}
山 茶树 和 葡萄 树
źródło