Jak mam przeanalizować JSON za pomocą Node.js? Czy jest jakiś moduł, który bezpiecznie zweryfikuje i parsuje JSON?
Jak mam przeanalizować JSON za pomocą Node.js? Czy jest jakiś moduł, który bezpiecznie zweryfikuje i parsuje JSON?
Odpowiedzi:
Możesz po prostu użyć JSON.parse
.
Definicja JSON
obiektu jest częścią specyfikacji ECMAScript 5 . node.js jest oparty na silniku V8 Google Chrome , który jest zgodny ze standardem ECMA. Dlatego node.js ma również obiekt globalny [docs] .JSON
Uwaga - JSON.parse
może powiązać bieżący wątek, ponieważ jest to metoda synchroniczna. Jeśli więc planujesz parsować duże obiekty JSON, użyj parsera strumieniowego json.
możesz wymagać plików .json.
var parsedJSON = require('./file-name');
Na przykład, jeśli config.json
plik znajduje się w tym samym katalogu, co plik kodu źródłowego, należy użyć:
var config = require('./config.json');
lub (rozszerzenie pliku można pominąć):
var config = require('./config');
zauważ, że require
jest synchroniczny i czyta plik tylko raz , kolejne wywołania zwracają wynik z pamięci podręcznej
Pamiętaj również, że powinieneś używać tego tylko do plików lokalnych pod twoją absolutną kontrolą, ponieważ potencjalnie wykonuje on dowolny kod w pliku.
require
jest synchroniczny. Jeśli fs.readFile
zamiast tego chcesz zsynchronizować przyjazne użycieJSON.parse
.json
rozszerzenia! Jeśli twój plik NIE ma .json
rozszerzenia, polecenie wymaga nie będzie traktować go jako pliku json.
Możesz użyćJSON.parse()
.
Powinieneś być w stanie używać tego JSON
obiektu w dowolnej implementacji JavaScript kompatybilnej z ECMAScript 5 . I V8 , na którym zbudowano Node.js, jest jednym z nich.
Uwaga: jeśli używasz pliku JSON do przechowywania poufnych informacji (np. Haseł), jest to niewłaściwy sposób. Zobacz, jak robi to Heroku: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Dowiedz się, jak robi to Twoja platforma, i użyj,
process.env
aby pobrać zmienne konfiguracji z kodu.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
Będziesz musiał wykonać kilka operacji na plikach za pomocą fs
modułu.
var fs = require('fs');
fs.readFile('/path/to/file.json', 'utf8', function (err, data) {
if (err) throw err; // we'll not consider error handling for now
var obj = JSON.parse(data);
});
var fs = require('fs');
var json = JSON.parse(fs.readFileSync('/path/to/file.json', 'utf8'));
require
? Pomyśl jeszcze raz!var obj = require('path/to/file.json');
Ale nie polecam tego z kilku powodów:
require
jest synchroniczny. Jeśli masz bardzo duży plik JSON, dusi on twoją pętlę zdarzeń. Naprawdę trzeba korzystać JSON.parse
z fs.readFile
.require
odczyta plik tylko raz . Kolejne wywołania require
tego samego pliku zwrócą kopię z pamięci podręcznej. Nie jest to dobry pomysł, jeśli chcesz czytać .json
plik, który jest stale aktualizowany. Możesz użyć hacka . Ale w tym momencie łatwiej jest po prostu użyć fs
..json
rozszerzenia, require
nie będzie traktować zawartości pliku jako JSON.Poważnie! ZastosowanieJSON.parse
.
load-json-file
modułJeśli czytasz dużą liczbę .json
plików (i jesteś wyjątkowo leniwy), pisanie kodu bojlera za każdym razem staje się denerwujące. Możesz zapisać niektóre znaki za pomocą load-json-file
modułu.
const loadJsonFile = require('load-json-file');
loadJsonFile('/path/to/file.json').then(json => {
// `json` contains the parsed object
});
let obj = loadJsonFile.sync('/path/to/file.json');
Jeśli zawartość JSON jest przesyłana strumieniowo przez sieć, musisz użyć analizatora składni JSON przesyłanego strumieniowo. W przeciwnym razie spowoduje to powiązanie procesora i uduszenie pętli zdarzeń do momentu pełnego przesłania treści JSON.
W tym celu dostępnych jest wiele pakietów w NPM . Wybierz to, co dla Ciebie najlepsze.
Jeśli nie masz pewności, czy cokolwiek, co jest przekazywane, JSON.parse()
jest poprawnym JSON , upewnij się, że dołączasz wywołanie do JSON.parse()
wewnątrz try/catch
bloku. Podany przez użytkownika ciąg JSON może spowodować awarię aplikacji, a nawet doprowadzić do luk w zabezpieczeniach. Upewnij się, że obsługa błędów jest wykonywana, jeśli analizujesz JSON podany zewnętrznie.
and could even lead to security holes
z ciekawości, jak?
<script>...
, a błąd został przelany na stronę klienta, masz tam błąd XSS. Dlatego IMO jest ważne, aby obsługiwać błędy JSON dokładnie tam, gdzie je analizujesz.
require
JSON?” i nawet nie zawracał sobie głowy dokumentowaniem skutków ubocznych. Oznaczało to również, że wymagany akceptuje pliki w dwóch językach: JavaScript i JSON (nie, nie są takie same). Tyle o SRP.
użyj obiektu JSON :
JSON.parse(str);
Kolejny przykład JSON.parse:
var fs = require('fs');
var file = __dirname + '/config.json';
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
console.dir(data);
});
Chciałbym wspomnieć, że istnieją alternatywy dla globalnego obiektu JSON.
JSON.parse
i JSON.stringify
oba są synchroniczne, więc jeśli chcesz radzić sobie z dużymi obiektami, możesz chcieć sprawdzić niektóre asynchroniczne moduły JSON.
Zobacz: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
całą aplikację ulegnie awarii lub, przy użyciu process.on('uncaughtException', function(err) { ... });
, ostatecznie nie będzie szansy na wysłanie użytkownikowi błędu „źle zniekształcony JSON”.
async
parser? Nie znalazłem tego.
Dołącz node-fs
bibliotekę.
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Aby uzyskać więcej informacji na temat biblioteki „fs”, zapoznaj się z dokumentacją pod adresem http://nodejs.org/api/fs.html
Ponieważ nie wiesz, że Twój ciąg jest rzeczywiście prawidłowy, postawiłbym go na pierwszym miejscu w próbach catch. Ponieważ bloki try catch nie są zoptymalizowane według węzłów, chciałbym umieścić całą tę funkcję w innej funkcji:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
LUB w „stylu asynchronicznym”
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
Analizujesz strumień JSON? Zastosowanie JSONStream
.
var request = require('request')
, JSONStream = require('JSONStream')
request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
.pipe(JSONStream.parse('rows.*'))
.pipe(es.mapSync(function (data) {
return data
}))
Wszyscy tutaj opowiadali o JSON.parse, więc pomyślałem o czymś innym. Istnieje świetny moduł Połącz z wieloma oprogramowaniem pośredniczącym, aby ułatwić i usprawnić tworzenie aplikacji. Jednym z programów pośrednich jest bodyParser . Analizuje JSON, formularze HTML itp. Istnieje również specyficzne oprogramowanie pośrednie do analizowania JSON tylko noop .
Spójrz na powyższe linki, może to być naprawdę pomocne.
JSON.parse("your string");
To wszystko.
jak wspomniano w innych odpowiedziach, prawdopodobnie potrzebujesz albo lokalnego pliku json, o którym wiesz, że jest bezpieczny i obecny, jak plik konfiguracyjny:
var objectFromRequire = require('path/to/my/config.json');
lub użyć globalnego obiektu JSON do parsowania wartości ciągu na obiekt:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
zwróć uwagę, że gdy potrzebujesz pliku, jego zawartość jest oceniana, co stwarza zagrożenie bezpieczeństwa w przypadku, gdy nie jest to plik json, ale plik js.
tutaj opublikowałem demo, w którym możesz zobaczyć obie metody i grać z nimi online (przykład parsowania znajduje się w pliku app.js - następnie kliknij przycisk Uruchom i zobacz wynik w terminalu): http: // staging1 .codefresh.io / labs / api / env / json-parse-example
możesz zmodyfikować kod i zobaczyć wpływ ...
Używasz JSON do konfiguracji z Node.js? Przeczytaj to i zdobądź umiejętności konfiguracyjne ponad 9000 ...
Uwaga: osoby twierdzące, że dane = wymagają („./ data.json”); jest zagrożeniem dla bezpieczeństwa i odrzuca odpowiedzi ludzi z gorliwym zapałem: Dokładnie i całkowicie się mylisz . Spróbuj umieścić plik inny niż JSON w tym pliku ... Węzeł wyświetli błąd, dokładnie tak , jak gdyby zrobiłeś to samo z dużo wolniejszym i trudniejszym kodowaniem ręcznego odczytu pliku, a następnie JSON.parse (). Przestańcie rozpowszechniać dezinformacje; ranisz świat, nie pomagasz. Węzeł został zaprojektowany, aby to umożliwić; to nie jest zagrożenie bezpieczeństwa!
Odpowiednie aplikacje są dostępne w ponad 3 warstwach konfiguracji:
Większość programistów traktuje konfigurację serwera i aplikacji tak, jakby mogła się zmienić. Nie może Możesz nakładać na siebie zmiany z wyższych warstw, ale modyfikujesz wymagania podstawowe . Niektóre rzeczy muszą istnieć! Spraw, by twoja konfiguracja zachowywała się tak, jakby była niezmienna, ponieważ niektóre z nich są po prostu, podobnie jak kod źródłowy.
Brak dostrzeżenia, że wiele rzeczy nie zmieni się po uruchomieniu, prowadzi do anty-wzorców, takich jak zaśmiecanie konfiguracji ładowaniem blokami try / catch i udawanie, że możesz kontynuować bez poprawnie skonfigurowanej aplikacji. Nie możesz Jeśli możesz, należy do warstwy konfiguracji społeczności / użytkowników, a nie warstwy konfiguracji serwera / aplikacji. Po prostu źle to robisz. Opcjonalne elementy należy nakładać warstwami na wierzch, gdy aplikacja zakończy ładowanie.
Przestań walić głową w ścianę: Twoja konfiguracja powinna być bardzo prosta .
Zobacz, jak łatwo jest skonfigurować coś tak złożonego, jak platforma usługowa niezależna od protokołu i od źródła danych przy użyciu prostego pliku konfiguracyjnego json i prostego pliku app.js ...
container-config.js ...
{
"service": {
"type" : "http",
"name" : "login",
"port" : 8085
},
"data": {
"type" : "mysql",
"host" : "localhost",
"user" : "notRoot",
"pass" : "oober1337",
"name" : "connect"
}
}
index.js ... (silnik, który napędza wszystko)
var config = require('./container-config.json'); // Get our service configuration.
var data = require(config.data.type); // Load our data source plugin ('npm install mysql' for mysql).
var service = require(config.service.type); // Load our service plugin ('http' is built-in to node).
var processor = require('./app.js'); // Load our processor (the code you write).
var connection = data.createConnection({ host: config.data.host, user: config.data.user, password: config.data.pass, database: config.data.name });
var server = service.createServer(processor);
connection.connect();
server.listen(config.service.port, function() { console.log("%s service listening on port %s", config.service.type, config.service.port); });
app.js ... (kod, który zasila twoją usługę agnostyczną niezależną od protokołu i źródła danych)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
Korzystając z tego wzorca, możesz teraz załadować elementy konfiguracji społeczności i użytkowników na uruchomioną aplikację, programista jest gotowy, aby wrzucić twoją pracę do kontenera i skalować. Jesteś czytany za multitenanta. Userland jest odizolowany. Możesz teraz rozdzielić obawy dotyczące używanego protokołu usługi, używanego typu bazy danych i skoncentrować się na pisaniu dobrego kodu.
Ponieważ używasz warstw, można polegać na jednym źródle prawdy za wszystko, w dowolnym momencie (warstwowy obiektu config) i kontroli błędów unikać na każdym kroku, martwiąc się o „O cholera, jak mam zamiar zrobić to pracować bez odpowiedniej konfiguracji?!? ".
Moje rozwiązanie:
var fs = require('fs');
var file = __dirname + '/config.json';
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
console.dir(data);
});
TypeError: path must be a string or Buffer
błędy - jakiś pomysł, od czego zacząć debugowanie tego problemu?
Po prostu chcę uzupełnić odpowiedź (ponieważ zmagałem się z nią przez chwilę), chcę pokazać, jak uzyskać dostęp do informacji json, ten przykład pokazuje dostęp do tablicy Json:
var request = require('request');
request('https://server/run?oper=get_groups_joined_by_user_id&user_id=5111298845048832', function (error, response, body) {
if (!error && response.statusCode == 200) {
var jsonArr = JSON.parse(body);
console.log(jsonArr);
console.log("group id:" + jsonArr[0].id);
}
})
Aby uczynić to tak skomplikowanym, jak to możliwe i przynieść jak najwięcej paczek, jak to możliwe ...
const fs = require('fs');
const bluebird = require('bluebird');
const _ = require('lodash');
const readTextFile = _.partial(bluebird.promisify(fs.readFile), _, {encoding:'utf8',flag:'r'});
const readJsonFile = filename => readTextFile(filename).then(JSON.parse);
Pozwala to na:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
Lub jeśli używasz asynchronizacji / czekaj:
let data = await readJsonFile("foo.json");
Zaletą readFileSync
tego jest fakt, że serwer Node może przetwarzać inne żądania podczas odczytywania pliku z dysku.
JSON.parse nie zapewni bezpieczeństwa analizowanego ciągu json. Powinieneś spojrzeć na bibliotekę taką jak json-safe-pars lub podobną bibliotekę.
Ze strony json-safe-parse npm:
JSON.parse jest świetny, ale ma jedną poważną wadę w kontekście JavaScript: pozwala zastąpić odziedziczone właściwości. Może to stać się problemem, jeśli analizujesz JSON z niezaufanego źródła (np. Użytkownika) i wywołujesz funkcje na nim, które prawdopodobnie istniałyby.
Wykorzystaj funkcję prób Lodash, aby zwrócić obiekt błędu, który możesz obsłużyć za pomocą funkcji isError.
// Returns an error object on failure
function parseJSON(jsonString) {
return _.attempt(JSON.parse.bind(null, jsonString));
}
// Example Usage
var goodJson = '{"id":123}';
var badJson = '{id:123}';
var goodResult = parseJSON(goodJson);
var badResult = parseJSON(badJson);
if (_.isError(goodResult)) {
console.log('goodResult: handle error');
} else {
console.log('goodResult: continue processing');
}
// > goodResult: continue processing
if (_.isError(badResult)) {
console.log('badResult: handle error');
} else {
console.log('badResult: continue processing');
}
// > badResult: handle error
.bind
zamiast po prostu używać _.attempt (JSON.parse, str)
Zawsze upewnij się, że używasz JSON.parse w try catch catch , ponieważ węzeł zawsze generuje nieoczekiwany błąd, jeśli masz jakieś uszkodzone dane w swoim jsonie, więc użyj tego kodu zamiast prostego JSON.Parse
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
Jeśli chcesz dodać kilka komentarzy do swojego JSON i zezwolić na przecinki końcowe, możesz użyć poniższej implementacji:
var fs = require('fs');
var data = parseJsData('./message.json');
console.log('[INFO] data:', data);
function parseJsData(filename) {
var json = fs.readFileSync(filename, 'utf8')
.replace(/\s*\/\/.+/g, '')
.replace(/,(\s*\})/g, '}')
;
return JSON.parse(json);
}
Pamiętaj, że może nie działać dobrze, jeśli masz coś takiego "abc": "foo // bar"
w swoim JSON. Więc YMMV.
Jeśli plik źródłowy JSON jest dość duży, warto rozważyć trasę asynchroniczną za pomocą natywnego asynchronizacji / oczekiwania na Node.js 8.0 w następujący sposób
const fs = require('fs')
const fsReadFile = (fileName) => {
fileName = `${__dirname}/${fileName}`
return new Promise((resolve, reject) => {
fs.readFile(fileName, 'utf8', (error, data) => {
if (!error && data) {
resolve(data)
} else {
reject(error);
}
});
})
}
async function parseJSON(fileName) {
try {
return JSON.parse(await fsReadFile(fileName));
} catch (err) {
return { Error: `Something has gone wrong: ${err}` };
}
}
parseJSON('veryBigFile.json')
.then(res => console.log(res))
.catch(err => console.log(err))
Używam fs-extra . Bardzo mi się podoba, ponieważ - choć obsługuje oddzwanianie - obsługuje także obietnice . Pozwala mi to po prostu napisać kod w znacznie bardziej czytelny sposób:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
Ma również wiele przydatnych metod, które nie są dostarczane wraz ze standardowym fs
modułem, a ponadto łączy je z fs
modułem macierzystym i obiecuje.
UWAGA: Nadal możesz używać natywnych metod Node.js. Są obiecane i kopiowane do fs-extra. Zobacz uwagi na temat
fs.read()
&fs.write()
To w zasadzie wszystkie zalety. Mam nadzieję, że inni uznają to za przydatne.
Jeśli chcesz parsować JSON z Node.js w bezpieczny sposób (aka: użytkownik może wprowadzać dane lub publiczny interfejs API) sugerowałbym użycie bezpiecznego parsowania .
Użycie jest jak domyślne, JSON.parse
ale ochroni Twój kod przed:
const badJson = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "constructor": {"prototype": {"bar": "baz"} } }'
const infected = JSON.parse(badJson)
console.log(infected.x) // print undefined
const x = Object.assign({}, infected)
console.log(x.x) // print 7
const sjson = require('secure-json-parse')
console.log(sjson.parse(badJson)) // it will throw by default, you can ignore malicious data also
Możesz użyć JSON.parse () (która jest wbudowaną funkcją, która prawdopodobnie zmusi cię do zawinięcia jej instrukcjami try-catch).
Lub użyj biblioteki JSON do analizowania npm, na przykład json-parse-or
Użyj tego, aby być po bezpiecznej stronie
var data = JSON.parse(Buffer.concat(arr).toString());
NodeJs jest serwerem opartym na JavaScript , więc możesz robić to tak, jak w czystym JavaScript ...
Wyobraź sobie, że to Json w NodeJs ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
Możesz to zrobić powyżej, aby uzyskać parsowaną wersję swojego jsona ...
Jak wspomniano w powyższych odpowiedziach, możemy użyć JSON.parse()
do parsowania napisów do JSON. Ale przed parsowaniem upewnij się, że parsujesz poprawne dane, w przeciwnym razie może to doprowadzić do awarii całej aplikacji
można go bezpiecznie używać w ten sposób
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Zastosowanie JSON.parse(str);
. Przeczytaj więcej na ten temat tutaj .
Oto kilka przykładów:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
To proste, możesz przekonwertować JSON na ciąg za pomocą JSON.stringify(json_obj)
i przekonwertować ciąg na JSON za pomocą JSON.parse("your json string")
.