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 JSONobiektu 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.parsemoż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.jsonplik 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 requirejest 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.
requirejest synchroniczny. Jeśli fs.readFilezamiast tego chcesz zsynchronizować przyjazne użycieJSON.parse
.jsonrozszerzenia! Jeśli twój plik NIE ma .jsonrozszerzenia, polecenie wymaga nie będzie traktować go jako pliku json.
Możesz użyćJSON.parse() .
Powinieneś być w stanie używać tego JSONobiektu 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.envaby 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ą fsmoduł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:
requirejest synchroniczny. Jeśli masz bardzo duży plik JSON, dusi on twoją pętlę zdarzeń. Naprawdę trzeba korzystać JSON.parsez fs.readFile.requireodczyta plik tylko raz . Kolejne wywołania requiretego samego pliku zwrócą kopię z pamięci podręcznej. Nie jest to dobry pomysł, jeśli chcesz czytać .jsonplik, który jest stale aktualizowany. Możesz użyć hacka . Ale w tym momencie łatwiej jest po prostu użyć fs..jsonrozszerzenia, requirenie będzie traktować zawartości pliku jako JSON.Poważnie! ZastosowanieJSON.parse .
load-json-file modułJeśli czytasz dużą liczbę .jsonplikó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-filemoduł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/catchbloku. 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 holesz 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.
requireJSON?” 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.parsei JSON.stringifyoba 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.parsecałą 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”.
asyncparser? Nie znalazłem tego.
Dołącz node-fsbibliotekę.
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 Bufferbłę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ą readFileSynctego 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
.bindzamiast 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 fsmodułem, a ponadto łączy je z fsmoduł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.parseale 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").