Node.js kullanarak JSON'u nasıl ayrıştırmalıyım? JSON'u güvenli bir şekilde doğrulayacak ve ayrıştıracak bazı modül var mı?
Node.js kullanarak JSON'u nasıl ayrıştırmalıyım? JSON'u güvenli bir şekilde doğrulayacak ve ayrıştıracak bazı modül var mı?
Yanıtlar:
Sadece kullanabilirsiniz JSON.parse
.
JSON
Nesnenin tanımı ECMAScript 5 spesifikasyonunun bir parçasıdır . node.js, Google Chrome'un ECMA standardına uygun V8 motoru üzerine kurulmuştur . Bu nedenle, node.js ayrıca küresel bir nesneye sahiptir [dokümanlar] .JSON
Not - JSON.parse
senkronize bir yöntem olduğu için mevcut evre bağlanabilir. Eğer büyük JSON nesneleri ayrıştırmak planlıyorsanız Yani bir akış json ayrıştırıcı kullanın.
Eğer yapabilirsiniz gerektiren dosyaları .json.
var parsedJSON = require('./file-name');
Örneğin config.json
, kaynak kod dosyanızla aynı dizinde bir dosyanız varsa şunları kullanırsınız:
var config = require('./config.json');
veya (dosya uzantısı atlanabilir):
var config = require('./config');
Not require
olan senkron ve sadece dosyasını okur kez , aşağıdaki aramalar önbellekten sonucu döndüren
Ayrıca, bunu yalnızca mutlak denetiminiz altındaki yerel dosyalar için kullanmanız gerekir, çünkü dosya içindeki herhangi bir kodu çalıştırır.
require
senkronize olduğunu da unutmayın . fs.readFile
Bunun yerine async dostu kullanım istiyorsanızJSON.parse
.json
uzantıyı kullanmayı unutmayın ! Dosyanız .json
uzantıya sahip DEĞİLDİR , gerektiren bir json dosyası olarak işlemez.
KullanabilirsinizJSON.parse()
.
Kullanılacak gerekir JSON
herhangi nesneyi ECMAScript 5 uyumlu JavaScript uygulaması. Ve Node.js'nin üzerine inşa edildiği V8 bunlardan biri.
Not: Hassas bilgileri (örn. Şifreler) saklamak için bir JSON dosyası kullanıyorsanız, bunu yapmanın yanlış yolu budur. Heroku'nun bunu nasıl yaptığını görün: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . Platformunuzun nasıl çalıştığını öğrenin
process.env
ve yapılandırmayı almak için kodun içinden değişiklik gösterir.
var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);
fs
Modül ile bazı dosya işlemleri yapmanız gerekir .
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
? Tekrar düşün!Bazen şunları kullanabilirsinizrequire
:
var obj = require('path/to/file.json');
Ancak, bunu birkaç nedenden dolayı önermiyorum:
require
eşzamanlıdır. Çok büyük bir JSON dosyanız varsa, olay döngünüzü boğar. Gerçekten kullanmak gerekir JSON.parse
ile fs.readFile
.require
dosyayı yalnızca bir kez okuyacaktır . require
Aynı dosya için sonraki çağrılar önbelleğe alınmış bir kopya döndürür. .json
Sürekli güncellenen bir dosyayı okumak istiyorsanız iyi bir fikir değildir . Bir kesmek kullanabilirsiniz . Ancak bu noktada, kullanımı daha kolaydır fs
..json
uzantısı yoksa, dosyanın require
içeriğini JSON olarak işlemez.Ciddi anlamda! KullanınJSON.parse
.
load-json-file
modülÇok sayıda .json
dosya okuyorsanız (ve aşırı derecede tembelseniz), her seferinde demirbaş kodu yazmak rahatsız edici olur. load-json-file
Modülü kullanarak bazı karakterleri kaydedebilirsiniz .
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');
JSON içeriği ağ üzerinden aktarılıyorsa, akışlı bir JSON ayrıştırıcı kullanmanız gerekir. Aksi takdirde, işlemcinizi bağlar ve JSON içeriği tamamen akışına ulaşıncaya kadar olay döngüsünü boğar.
Bunun için NPM'de çok sayıda paket var . Sizin için en iyisini seçin.
Emin değilseniz, her ne ise o geçirilir JSON.parse()
ise geçerli JSON , çağrısına içine emin olun JSON.parse()
bir iç try/catch
bloğun. Kullanıcı tarafından sağlanan JSON dizesi uygulamanızı kilitleyebilir ve hatta güvenlik açıklarına neden olabilir. Harici olarak sağlanan JSON'ı ayrıştırırsanız hata işlemenin yapıldığından emin olun.
and could even lead to security holes
meraktan nasıl?
<script>...
ve hata istemci tarafına dökülürse, orada bir XSS hatası vardır. Bu nedenle IMO, ayrıştırdığınız yerde JSON hatalarını işlemek önemlidir.
require
JSON'u dahil etmek iyi olmaz mıydı ?" ve yan etkileri belgelemeye bile gerek yok. Bu aynı zamanda iki dilde dosyaları kabul etmeyi gerektiren anlamına da geliyordu: JavaScript ve JSON (hayır aynı değiller). SRP için çok fazla.
JSON nesnesini kullanın :
JSON.parse(str);
JSON.parse'ın başka bir örneği:
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);
});
Global JSON nesnesine alternatifler olduğunu belirtmek isterim.
JSON.parse
ve JSON.stringify
her ikisi de eşzamanlıdır, bu nedenle büyük nesnelerle uğraşmak istiyorsanız, eşzamansız JSON modüllerinden bazılarına göz atmak isteyebilirsiniz.
Bir göz atın: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json
JSON.parse
tüm uygulamanız tarafından çöküyor veya kullanıldığında process.on('uncaughtException', function(err) { ... });
, sonunda kullanıcıya "hatalı biçimlendirilmiş JSON" hatası gönderme şansı olmayacaktır.
async
ayrıştırıcıdır? Bulamadım.
node-fs
Kütüphaneyi ekleyin .
var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
'Fs' kütüphanesi hakkında daha fazla bilgi için http://nodejs.org/api/fs.html adresindeki belgelere bakın.
Dizenizin aslında geçerli olduğunu bilmediğiniz için, önce bir deneme yakalamaya koyarım. Ayrıca try catch blokları düğüm tarafından optimize edilmediğinden, her şeyi başka bir fonksiyona koyarım:
function tryParseJson(str) {
try {
return JSON.parse(str);
} catch (ex) {
return null;
}
}
VEYA "zaman uyumsuz stil"
function tryParseJson(str, callback) {
process.nextTick(function () {
try {
callback(null, JSON.parse(str));
} catch (ex) {
callback(ex)
}
})
}
JSON akışını ayrıştırma? Kullanın 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
}))
Buradaki herkes JSON.parse'dan bahsetti, bu yüzden başka bir şey söylemeyi düşündüm. Uygulamaların geliştirilmesini daha kolay ve daha iyi hale getirmek için birçok ara katmana bağlanın harika bir modül var . Ara katman yazılımlarından biri bodyParser . JSON, html-formları vb . Ayrıştırır . JSON yalnızca noop ayrıştırma için özel bir ara katman yazılımı da vardır .
Yukarıdaki bağlantılara bir göz atın, size gerçekten yardımcı olabilir.
JSON.parse("your string");
Bu kadar.
Buradaki diğer yanıtların belirttiği gibi, muhtemelen bir yapılandırma dosyası gibi güvenli ve mevcut olduğunu bildiğiniz yerel bir json dosyasına ihtiyaç duymak istersiniz:
var objectFromRequire = require('path/to/my/config.json');
veya bir dize değerini bir nesneye ayrıştırmak için global JSON nesnesini kullanmak için:
var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
bir dosyaya ihtiyaç duyduğunuzda, o dosyanın içeriğinin değerlendirildiğini unutmayın; bu bir json dosyası değil, bir js dosyası olması durumunda bir güvenlik riski oluşturur.
Burada, her iki yöntemi de görebileceğiniz ve onlarla çevrimiçi oynayabileceğiniz bir demo yayınladım (ayrıştırma örneği app.js dosyasındadır - daha sonra çalıştırma düğmesine tıklayın ve terminalde sonucu görün): http: // staging1 .codefresh.io / labs / aPI / env / json-ayrıştırma örnek
kodu değiştirebilir ve etkisini görebilirsiniz ...
Node.js ile yapılandırmanız için JSON mu kullanıyorsunuz? Bunu okuyun ve 9000'in üzerinde yapılandırma becerilerinizi edinin ...
Not: Verinin = gerekli olduğunu iddia eden kişiler ('./ data.json'); bir güvenlik riski ve gayretli gayretle insanların cevaplarını küçümsüyor: Tam ve tamamen yanılıyorsunuz . Bu dosyada olmayan JSON yerleştirmeyi deneyin ... Düğüm size bir hata verecektir tam olarak size aynısını yaptı eğer yaptığımız gibi çok kod manuel dosya okuma yavaş ve daha sert ve daha sonraki JSON.parse (). Lütfen yanlış bilgi yaymayı bırakın; dünyaya zarar veriyorsun, yardım etmiyorsun. Düğüm buna izin verecek şekilde tasarlanmıştır ; bu bir güvenlik riski değildir!
Uygun uygulamalar 3+ yapılandırma katmanında gelir :
Çoğu geliştirici, sunucularına ve uygulama yapılandırmalarına değişebilir gibi davranır. Yapamaz. Daha yüksek katmanlardaki değişiklikleri üst üste katmanlayabilirsiniz, ancak temel gereksinimleri değiştirirsiniz . Bazı şeylerin var olması gerekir ! Yapılandırmanızın değişmez gibi davranmasını sağlayın, çünkü bazıları kaynak kodunuz gibi.
Başlangıçtan sonra birçok öğenizin değişmeyeceğini görmemeniz, yapılandırma yüklemenizi try / catch blokları ile kirletmek ve düzgün kurulum uygulamanız olmadan devam edebileceğiniz gibi davranmak gibi anti-desenlere yol açar . Yapamazsın. Yapabiliyorsanız, bu sunucu / uygulama yapılandırma katmanına değil topluluk / kullanıcı yapılandırma katmanına aittir. Sadece yanlış yapıyorsun. Uygulama önyükleme işlemini tamamladığında isteğe bağlı öğeler üstte katmanlanmalıdır.
Başınızı duvara vurmayı bırakın: Konfigürasyonunuz çok basit olmalıdır .
Basit bir json yapılandırma dosyası ve basit app.js dosyası kullanarak protokol-agnostik ve veri kaynağı-agnostik hizmet çerçevesi kadar karmaşık bir şey kurmanın ne kadar kolay olduğuna bir göz atın ...
Konteyner-config.js ...
{
"service": {
"type" : "http",
"name" : "login",
"port" : 8085
},
"data": {
"type" : "mysql",
"host" : "localhost",
"user" : "notRoot",
"pass" : "oober1337",
"name" : "connect"
}
}
index.js ... (her şeye güç veren motor)
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 ... (protokol agnostik ve veri kaynağı agnostik hizmetinize güç veren kod)
module.exports = function(request, response){
response.end('Responding to: ' + request.url);
}
Bu kalıbı kullanarak, artık önyükleme uygulamanızın üstüne topluluk ve kullanıcı yapılandırma öğelerini yükleyebilirsiniz, dev ops çalışmanızı bir kaba aktarmaya ve ölçeklemeye hazırdır. Çok kullanıcılılar için okundunuz. Userland izole edilmiştir. Artık hangi servis protokolünü kullandığınızı, hangi veritabanı türünü kullandığınızı ve sadece iyi kod yazmaya odaklanın.
Katmanları kullanarak Çünkü, oh bok, nasıl yapacağım" endişesi, herhangi bir zamanda (katmanlı yapılandırma nesne) de, her şey için gerçeğin tek bir kaynaktan güvenmek ve her adımda önlemek hata kontrolleri yapabilirsiniz bu düzgün yapılandırma olmadan çalışmak?!? ".
Çözümüm:
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
hata almaya devam ediyorum - herhangi bir fikir nerede bu hata ayıklama başlamak için?
Sadece cevabı tamamlamak istiyorum (bir süre bununla mücadele ederken), json bilgilerine nasıl erişileceğini göstermek istiyorum, bu örnek Json Array'a erişmeyi gösteriyor:
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);
}
})
Bunu mümkün olduğunca karmaşık hale getirmek ve mümkün olduğunca çok paket getirmek ...
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);
Bu şunları yapmanızı sağlar:
var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);
Veya async / await kullanıyorsanız:
let data = await readJsonFile("foo.json");
Sadece kullanmanın avantajı readFileSync
, Node sunucunuzun dosya diski okunurken diğer istekleri işleyebilmesidir.
JSON.parse, ayrıştırdığınız json dizesinin güvenliğini sağlamaz. Json-safe-parse gibi bir kütüphaneye veya benzer bir kütüphaneye bakmalısınız .
Json-safe-parse npm sayfasından:
JSON.parse harika, ancak JavaScript bağlamında ciddi bir kusuru var: devralınan özellikleri geçersiz kılmanıza izin verir. JSON'u güvenilir olmayan bir kaynaktan (örneğin: bir kullanıcı) ayrıştırırsanız ve bunun üzerinde var olmasını beklediğiniz işlevleri çağırırsanız bu bir sorun haline gelebilir.
İsError işleviyle işleyebileceğiniz bir hata nesnesi döndürmek için Lodash'ın deneme işlevinden yararlanın.
// 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
Sadece _.attempt (JSON.parse, str) kullanmak yerine neden eklediğinizi açıklayabilir misiniz
Json'unuzda bazı bozuk veriler varsa, düğüm her zaman beklenmedik bir hata attığından deneyin catch bloğunda her zaman JSON.parse kullandığınızdan emin olun, bu nedenle basit JSON yerine bu kodu kullanın.
try{
JSON.parse(data)
}
catch(e){
throw new Error("data is corrupted")
}
JSON'unuza bazı yorumlar eklemek ve sondaki virgüllere izin vermek istiyorsanız, aşağıdaki uygulamada kullanmak isteyebilirsiniz:
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);
}
JSON'unuzda olduğu gibi bir şey varsa iyi çalışmayabileceğini "abc": "foo // bar"
unutmayın. Yani YMMV.
JSON kaynak dosyası oldukça büyükse, Node.js 8.0 ile yerel asenkron / await yaklaşımı yoluyla asenkron rotayı aşağıdaki gibi düşünmek isteyebilirsiniz
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))
Ben fs-extra kullanıyorum . Bunu çok seviyorum çünkü geri çağrıları desteklese de Promises'ı da destekliyor . Bu yüzden kodumu çok daha okunabilir bir şekilde yazmamı sağlıyor:
const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
//Do dome stuff with obj
})
.catch(err => {
console.error(err);
});
Ayrıca, standart fs
modülle birlikte gelmeyen birçok yararlı yönteme sahiptir ve bunun üzerine, yerel fs
modüldeki yöntemleri de köprüler ve söz verir.
Not: yine de yerel Node.js yöntemlerini kullanabilirsiniz. Söz verildi ve fs-extra'ya kopyalandı.
fs.read()
& Üzerindeki notlara bakınfs.write()
Yani temelde tüm avantajları. Umarım diğerleri bunu faydalı bulur.
JSON'u Node.js ile güvenli bir şekilde ayrıştırmanız gerekiyorsa (aka: kullanıcı veri veya genel bir API girebilir) secure-json-parse kullanmanızı öneririm .
Kullanım varsayılan gibidir JSON.parse
ancak kodunuzu aşağıdakilerden koruyacaktır:
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
JSON.parse () işlevini kullanabilirsiniz (muhtemelen sizi try-catch deyimleriyle sarmaya zorlayacak yerleşik bir işlevdir).
Veya json-parse-veya
Güvenli tarafta olmak için bunu kullanın
var data = JSON.parse(Buffer.concat(arr).toString());
NodeJs bir olan JavaScript Eğer saf halinde bunu bir şekilde yapabilmeniz için tabanlı sunucu JavaScript ...
Düğümlerde bu Json olduğunu düşünün ...
var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);
Ve json'unuzun ayrıştırılmış bir sürümünü almak için yukarıda yapabilirsiniz ...
Yukarıdaki yanıtlarda belirtildiği gibi JSON.parse()
, dizeleri JSON'a çözümlemek için kullanabiliriz .
bu şekilde kullanmak güvenlidir
let parsedObj = {}
try {
parsedObj = JSON.parse(data);
} catch(e) {
console.log("Cannot parse because data is not is proper json format")
}
Kullanın JSON.parse(str);
. Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz .
İşte bazı örnekler:
var jsonStr = '{"result":true, "count":42}';
obj = JSON.parse(jsonStr);
console.log(obj.count); // expected output: 42
console.log(obj.result); // expected output: true
Çok basit, kullanarak JSON dizeye JSON.stringify(json_obj)
dönüştürebilirsiniz ve kullanarak JSON dizeye dönüştürebilirsiniz JSON.parse("your json string")
.