2010-11-17 15 views
14

json2.js jest rygorystycznym wymogiem, aby wszystkie klucze obiektu były podwójnie cytowane. Jednak w składni JavaScript {"foo":"bar"} jest równoważny {foo:"bar"}.Bezpieczne parsowanie łańcucha JSON z niecytowanymi kluczami

Mam textarea, która akceptuje dane wejściowe JSON od użytkownika i chce "ułatwić" ograniczenie podwójnego cytowania kluczy. Przyjrzałem się, jak json2.js sprawdza poprawność ciągu JSON w czterech etapach, zanim go zeskrobuje. Udało mi się dodać piąty etap, aby umożliwić niecytowanie kluczy i chciałbym się dowiedzieć, czy są jakieś implikacje dla bezpieczeństwa tej logiki.

var data = '{name:"hello", age:"23"}'; 

// Make sure the incoming data is actual JSON 
// Logic borrowed from http://json.org/json2.js 
if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") 
    .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") 
    .replace(/(?:^|:|,)(?:\s*\[)+/g, ":") // EDITED: allow key:[array] by replacing with safe char ":" 
    /** everything up to this point is json2.js **/ 

    /** this is the 5th stage where it accepts unquoted keys **/   
    .replace(/\w+\s*\:/g, ":"))) { // EDITED: allow any alphanumeric key 

    console.log((new Function("return " + data))()); 
} 
else { 
    throw("Invalid JSON: " + data); 
} 
+4

założyć obiekt JavaScript literał jest równoznaczne z JSON, który nie jest. – Stephen

+6

'{name:" Joe "}' jest poprawnym skryptem JavaScript, ale jest to _invalid_ JSON. Również nie chcesz zhakować 'json2.js', ponieważ odzwierciedla ono jedynie sposób działania macierzystej obsługi JSON w przeglądarkach. W Chrome na przykład, 'JSON.parse()' bez 'json2.js' również by się do tego dusiło. Ale gorsze jest to, że 'json2.js' nie ładuje niczego, jeśli przeglądarka ma natywną obsługę JSON. Będziesz więc w sytuacji, w której przeglądarki z natywnym wsparciem JSON nigdy nie zobaczą tego hacka, ponieważ zamiast tego używają natywnego kodu do parsowania. –

+0

@ Stephen Masz rację. Może powinienem przeformułować pytanie jako "Bezpiecznie parsując JavaScript Object Literal i konwertując do JSON"? – daepark

Odpowiedz

0

JSON nie zezwala na niecytowane klucze. JSON jest podzbiorem notacji JavaScript i nie zawiera kluczy niecytowanych. Przekazywanie niecytowanych kluczy do niemal dowolnego parsera JSON prawdopodobnie spowoduje błąd lub zwróci "nieoczekiwane" wyniki.

Nadzieja to pomaga

+3

Prawda o JSON oczywiście, ale JavaScript pozwala na niecytowane klucze w literałach obiektów. To tylko trochę problematyczne, ponieważ nie można używać myślników ani słów zarezerwowanych bez cudzysłowu. Myślę, że pytający już o tym wie. – JAL

3
data.replace(/(['"])?([a-zA-Z0-9]+)(['"])?:/g, '"$2":'); 

który zastąpi żadnych apostrofów na nazwę parametru i dodaj te, których brakuje.

+5

To wydaje się działać. Poza tym, że nie poradziłeś sobie z podkreśleniem. Oto zaktualizowane wyrażenie: 'hash.replace (/ (['"])? ([A-zA-Z0-9 _] +) ([' "])?:/G, '" $ 2 ":');' –

+0

touche, dziękuję, że to było przeoczenie –

+4

Ta odpowiedź jest daleka od ideału. Wypróbuj '{a: ['b', 'c']}' lub '{a:" Uwaga: coś się stało. "}' – powerboy

1

Pomyślałem, że pomocne byłoby posiadanie rzeczywistych przypadków testowych w celu usunięcia problemów związanych z tą implementacją. Dodałem projekt Github o nazwie JSOL z kilkoma testami. Wypełnij za darmo, aby dodać i znaleźć problemy. Dzięki.

https://github.com/daepark/JSOL