วิธีแยก JSON โดยใช้ Node.js


972

ฉันควรแยก JSON โดยใช้ Node.js อย่างไร มีโมดูลที่จะตรวจสอบและแยก JSON อย่างปลอดภัยหรือไม่?

คำตอบ:


1100

JSON.parseคุณก็สามารถใช้

ความหมายของJSONวัตถุที่เป็นส่วนหนึ่งของ ECMAScript 5 สเปค node.js สร้างขึ้นบนเครื่องมือV8ของ Google Chrome ซึ่งเป็นไปตามมาตรฐาน ECMA ดังนั้น Node.js นอกจากนี้ยังมีวัตถุโลก[เอกสาร]JSON

หมายเหตุ - JSON.parseสามารถผูกเธรดปัจจุบันได้เนื่องจากเป็นวิธีการซิงโครนัส ดังนั้นหากคุณวางแผนที่จะแยกวิเคราะห์วัตถุ JSON ขนาดใหญ่ให้ใช้ json parser แบบสตรีม


ใครรู้ว่าทำไมที่ไม่ได้อยู่ในเอกสารอย่างเป็นทางการ? หรือถ้าเป็นจะหาได้ที่ไหน
snapfractalpop

34
@snapfractalpop: เอกสารอธิบายเฉพาะฟังก์ชัน ฯลฯ ซึ่งเป็นส่วนหนึ่งของ node.js คุณลักษณะ JavaScript มาตรฐานเป็นส่วนหนึ่งของV8 , node.js ถูกสร้างขึ้นบน ฉันปรับปรุงคำตอบตามนั้น
เฟลิกซ์คลิง

1
@FelixKling สำหรับสิ่งที่คุ้มค่ามีหลายสิ่งที่นี่บนโหนด github wiki: github.com/joyent/node/wiki/…
damianb

ที่นี่ฉันได้เผยแพร่ตัวอย่างที่คุณสามารถดูและเล่นกับคำตอบนี้ออนไลน์ (ตัวอย่างการแยกวิเคราะห์อยู่ในไฟล์ app.js - จากนั้นคลิกที่ปุ่มเรียกใช้และดูผลลัพธ์ในเทอร์มินัล): ลิงก์ที่ คุณสามารถแก้ไขรหัสได้ และดูผลกระทบ ...
ธา

คำตอบของคุณต้องการความรู้ก่อนหน้าเกี่ยวกับไวยากรณ์ของ JavaScript มันจะยากแค่ไหนที่จะแสดงตัวอย่างการใช้งาน? JSON.parse (STR); // เป็นมิตรกับ noob และคำตอบที่ดีกว่า
webb

661

คุณสามารถต้องการไฟล์. json

var parsedJSON = require('./file-name');

ตัวอย่างเช่นหากคุณมีconfig.jsonไฟล์ในไดเรกทอรีเดียวกับไฟล์ซอร์สโค้ดของคุณคุณจะใช้:

var config = require('./config.json');

หรือ (สามารถตัดนามสกุลไฟล์ได้):

var config = require('./config');

ทราบว่าrequireเป็นซิงโครและมีเพียงอ่านไฟล์ครั้งเดียวโทรกลับต่อไปผลจากแคช

และโปรดทราบว่าคุณควรใช้สิ่งนี้กับไฟล์ในเครื่องภายใต้การควบคุมแบบสมบูรณ์ของคุณเท่านั้นเนื่องจากอาจมีการเรียกใช้รหัสใด ๆ ภายในไฟล์


4
หากคุณใช้วิธีนี้ในการแยกไฟล์ให้แน่ใจว่าได้คำนึงถึงเส้นทางสำหรับความต้องการ ตัวอย่างเช่นคุณอาจต้องทำสิ่งนี้: ต้องการ './file-name-with-no-extension' (ตัวอย่างเช่นหากไฟล์อยู่ในไดเรกทอรีปัจจุบัน)
SnapShot

94
โปรดทราบว่าการตอบสนองถูกแคช เช่นถ้าคุณใส่ข้างต้นจำเป็นต้องมีการเรียกใช้ในฟังก์ชันเรียกใช้ฟังก์ชันเปลี่ยนไฟล์ JSON และเรียกใช้ฟังก์ชันอีกครั้งคุณจะได้รับไฟล์ JSON เวอร์ชันเก่า ทำให้ฉันออกไปสองสามครั้ง!
Ben Clayton

15
หมายเหตุยังที่requireซิงโครนัส หากคุณต้องการใช้งานแบบเป็นมิตรfs.readFileแทนได้ด้วยJSON.parse
Evan Moran

29
วิธีนี้จะใช้กับไฟล์เป็น JavaScript หรือไม่ดังนั้นจึงอาจใช้รหัสโดยอำเภอใจในไฟล์. json
d11wtq

15
ข้อความง่ายๆ: อย่าลืมใช้.jsonส่วนขยาย! หากไฟล์ของคุณไม่มี.jsonนามสกุลต้องการจะไม่ถือว่าเป็นไฟล์ json
Jason

323

JSON.parse()คุณสามารถใช้

คุณควรจะสามารถใช้JSONออบเจ็กต์ในการใช้งาน JavaScript ที่ทำงานร่วมกับECMAScript 5ได้ และV8ซึ่ง Node.js ถูกสร้างขึ้นนั้นเป็นหนึ่งในนั้น

หมายเหตุ: หากคุณกำลังใช้ไฟล์ JSON เพื่อเก็บข้อมูลที่ละเอียดอ่อน (เช่นรหัสผ่าน) นั่นเป็นวิธีที่ผิดที่จะทำ ดูวิธีการ Heroku ไม่ได้: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application ค้นหาวิธีการที่แพลตฟอร์มของคุณใช้งานและใช้process.envเพื่อเรียกข้อมูล vars config จากภายในโค้ด


การแยกสตริงที่มีข้อมูล JSON

var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);

แยกไฟล์ที่มีข้อมูล JSON

คุณจะต้องดำเนินการกับไฟล์ด้วยfsโมดูล

เวอร์ชันอะซิงโครนัส

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หรือไม่ คิดอีกครั้ง!

บางครั้งคุณสามารถใช้require :

var obj = require('path/to/file.json');

แต่ฉันไม่แนะนำสิ่งนี้ด้วยเหตุผลหลายประการ:

  1. requireเป็นแบบซิงโครนัส หากคุณมีไฟล์ JSON ที่ใหญ่มากมันจะทำให้ห่วงเหตุการณ์ของคุณไม่สมบูรณ์ ที่คุณต้องการจริงๆที่จะใช้กับJSON.parsefs.readFile
  2. requireจะอ่านไฟล์ได้เพียงครั้งเดียว การเรียกrequireไฟล์ที่ตามมาครั้งต่อไปจะส่งคืนสำเนาที่แคชไว้ ไม่ใช่ความคิดที่ดีถ้าคุณต้องการอ่าน.jsonไฟล์ที่มีการปรับปรุงอย่างต่อเนื่อง คุณสามารถใช้แฮ็ค แต่ ณ fsจุดนี้มันง่ายต่อการใช้งานเพียงแค่
  3. หากไฟล์ของคุณไม่มี.jsonนามสกุลrequireจะไม่ถือว่าเนื้อหาของไฟล์เป็น JSON

อย่างจริงจัง! JSON.parseใช้


load-json-file โมดูล

หากคุณกำลังอ่าน.jsonไฟล์จำนวนมาก(และถ้าคุณขี้เกียจสุด ๆ ) มันจะน่ารำคาญที่จะเขียนโค้ดสำเร็จรูปทุกครั้ง คุณสามารถบันทึกอักขระบางตัวได้โดยใช้load-json-fileโมดูล

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 จากสตรีม

หากเนื้อหา JSON ถูกสตรีมผ่านเครือข่ายคุณต้องใช้ตัวแยกวิเคราะห์สตรีม JSON มิเช่นนั้นจะผูกตัวประมวลผลของคุณและทำให้ห่วงเหตุการณ์ของคุณจนกว่าเนื้อหา JSON จะถูกสตรีมเต็ม

มีแพคเกจมากมายใน NPMสำหรับสิ่งนี้ เลือกสิ่งที่ดีที่สุดสำหรับคุณ


การจัดการข้อผิดพลาด / ความปลอดภัย

หากคุณไม่แน่ใจว่าสิ่งที่ส่งผ่านไปJSON.parse()เป็นJSON ที่ถูกต้องให้แน่ใจว่าจะใส่การเรียกร้องให้JSON.parse()ภายในtry/catchบล็อก ผู้ใช้ที่ระบุสตริง JSON อาจทำให้แอปพลิเคชันของคุณทำงานขัดข้องและอาจนำไปสู่ช่องโหว่ด้านความปลอดภัย ตรวจสอบให้แน่ใจว่ามีการจัดการข้อผิดพลาดหากคุณแยกวิเคราะห์ JSON จากภายนอก


2
and could even lead to security holesจากความอยากรู้ได้อย่างไร
natario

6
@natario: เรากำลังพูดถึง JS ฝั่งเซิร์ฟเวอร์ที่นี่ สมมติว่ามีบางคนกำลังวิเคราะห์ JSON ที่ผู้ใช้จัดหา หากสมมติฐานคือ JSON นั้นมีรูปแบบที่ดีผู้โจมตีสามารถส่ง JSON ที่มีรูปแบบไม่ถูกต้องเพื่อทริกเกอร์ข้อผิดพลาดซึ่งหากหกไปยังฝั่งไคลเอ็นต์อาจเปิดเผยข้อมูลที่สำคัญเกี่ยวกับระบบ หรือถ้า JSON ทั้งสองมีรูปแบบไม่ถูกต้องและมีข้อความบางส่วนอยู่<script>...และข้อผิดพลาดถูกกระจายไปที่ฝั่งไคลเอ็นต์คุณมีข้อผิดพลาด XSS อยู่ที่นั่น ดังนั้น IMO จึงเป็นสิ่งสำคัญที่จะจัดการกับข้อผิดพลาด JSON ได้ทันทีที่คุณแยกวิเคราะห์
sampathsris

1
@NickSteele: อย่างไรก็ตามฉันเปลี่ยน "ไม่แนะนำ" เป็น "ฉันไม่แนะนำ" ฉันหวังว่าคุณจะมีความสุขในขณะนี้
sampathsris

1
@ NickSteele: เนื่องจากข้อบกพร่องที่ฉันได้ระบุไว้ฉันไม่คิดว่ามันเป็นคุณสมบัติที่ออกแบบมาอย่างดี ดูเหมือนว่าฉันบางคนคิดว่า "เฮ้มันจะเจ๋งrequireใช่มั้ยที่จะรวม JSON ด้วย" และไม่แม้แต่จะทำเอกสารเกี่ยวกับผลข้างเคียง สิ่งนี้หมายความว่าต้องยอมรับไฟล์ในสองภาษา: JavaScript และ JSON (ไม่เหมือนกัน) มากสำหรับ SRP
sampathsris

1
@NickSteele: ใช่เฉพาะการกำหนดค่าที่ทำงานได้ดี แต่ JSON ไม่ได้ใช้สำหรับการกำหนดค่าเท่านั้น
sampathsris

85

ใช้วัตถุ JSON :

JSON.parse(str);

12
นี่เป็นเพียงคำตอบที่ซ้ำกัน โปรดลองลบมัน คุณจะเก็บคะแนน
Dan Dascalescu

6
คำตอบนี้มี 50 upvotes ตามกฎ 1%อาจมีผู้ใช้ 5,000 รายที่ใช้เวลาอ่านคำตอบนี้ซึ่งไม่มีอะไรเพิ่มเข้ามาในอันดับต้น ๆ ความจริงที่ว่ามันอายุ 3 ขวบทำให้ปัญหาแย่ลง :)
Dan Dascalescu

16
@DanDascalescu - หากคุณสังเกตเห็นคำตอบทั้งสองนั้นถูกโพสต์ในเวลาเดียวกันเมื่อ 3 ปีก่อน พวกเขาทั้งสองให้ข้อมูลเดียวกัน นี่คือกรณีทั้งหมดดังนั้นฉันไม่ได้ไปเลือกสรรคำตอบของฉันเพียงครึ่งหนึ่งเพราะพวกเขาไม่ใช่คำตอบที่ยอมรับได้
Mark Kahn

8
ฉันพบหนึ่งความคิดเห็นชุดนี้น่าสนใจทีเดียว แต่คำตอบเองเสียเวลาของฉัน ... ฉันไม่แน่ใจว่านั่นหมายความว่าคำตอบควรถูกลบหรือไม่เพราะฉันจะไม่เห็นกระทู้ความคิดเห็น แต่อย่างอื่นฉันจะบอกว่าใช่
MalcolmOcean

7
@DanDascalescu ฉันเชื่อว่าคำตอบนี้ชัดเจนและตรงประเด็น ตัวอย่างที่ยอมรับไม่ได้ให้ตัวอย่างการใช้งานและสับสนเนื่องจากมีลิงค์และสิ่งเพิ่มเติมมากมาย
andresgottlieb

37

ตัวอย่างของ 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);
});

2
ฉันชอบที่วิธีการนี ขอบคุณ!
Charles Brandt

35

ฉันต้องการพูดถึงว่ามีทางเลือกอื่นสำหรับวัตถุ JSON ทั่วโลก JSON.parseและJSON.stringifyมีทั้งแบบซิงโครนัสดังนั้นหากคุณต้องการจัดการกับวัตถุขนาดใหญ่คุณอาจต้องการตรวจสอบโมดูล JSON แบบอะซิงโครนัสบางส่วน

ดูได้ที่: https://github.com/joyent/node/wiki/Modules#wiki-parsers-json


1
นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งหากมีใครคาดว่าข้อมูล JSON จากการเชื่อมต่อขาเข้า หาก JSON ที่มีรูปแบบไม่ถูกแยกวิเคราะห์โดยJSON.parseแอปพลิเคชันทั้งหมดของคุณกำลังจะขัดข้องหรือการใช้process.on('uncaughtException', function(err) { ... });ในที่สุดจะไม่มีโอกาสส่งข้อผิดพลาด "JSON ที่มีรูปแบบผิดพลาด" ไปยังผู้ใช้
พอล

3
เป็นที่หนึ่งที่asyncparser? ฉันไม่พบมัน
bxshi

3
ตอนนี้หน้าที่ลิงก์ถูกทำเครื่องหมาย "เลิกใช้แล้ว" และอธิบายตัวเองว่าเป็น "จางที่ระลึก"
ไม่มีใคร

30

รวมถึงnode-fsห้องสมุด

var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับห้องสมุด 'fs' โปรดดูเอกสารประกอบที่http://nodejs.org/api/fs.html


2
อาจเป็นเรื่องที่ควรสังเกตว่าคุณควรตัดบรรทัดไฟล์ var ของคุณในลอง / จับในกรณีที่ JSON ของคุณล้มเหลวในการแยกวิเคราะห์หรือไฟล์ไม่มีอยู่
Fostah

3
หรือเพียงแค่ใช้โทรกลับ!
lawx

10

เนื่องจากคุณไม่ทราบว่าสตริงของคุณใช้งานได้จริงฉันจะลองจับมันก่อน นอกจากนี้เนื่องจากการลอง catch catch block ไม่ได้รับการปรับแต่งโดยโหนดฉันจะใส่ทุกอย่างลงในฟังก์ชั่นอื่น:

function tryParseJson(str) {
    try {
        return JSON.parse(str);
    } catch (ex) {
        return null;
    }
}

หรือใน "async style"

function tryParseJson(str, callback) {
    process.nextTick(function () {
      try {
          callback(null, JSON.parse(str));
      } catch (ex) {
          callback(ex)
      }
    })
}

2
ฉันแค่ต้องการจดบันทึกว่า process.nextTick ไม่ใช่ aysnc มันเพิ่งเลื่อนการอ่านไฟล์ออกไปจนกระทั่งการเรียกใช้ฟังก์ชันถัดไปในเหตุการณ์วนรอบ JS ในการรัน JSON.parse แบบอะซิงโครนัสคุณได้ใช้เธรดที่แตกต่างจากเธรด Node.js หลัก
Alexander Mills


7

ทุกคนที่นี่บอกเกี่ยวกับ JSON.parse ดังนั้นฉันคิดว่าจะพูดอย่างอื่น มีโมดูลที่ยอดเยี่ยมเชื่อมต่อกับมิดเดิลแวร์จำนวนมากเพื่อให้การพัฒนาแอพง่ายขึ้นและดีขึ้น หนึ่งของมิดเดิ้ลเป็นbodyParser มันจะแยกวิเคราะห์ JSON, HTML รูปแบบและอื่น ๆ นอกจากนี้ยังมีตัวกลางที่เฉพาะเจาะจงสำหรับ JSON แยกเพียงnoop

ลองดูลิงค์ด้านบนมันอาจเป็นประโยชน์กับคุณจริงๆ



6

ดังที่คำตอบอื่น ๆ ที่นี่ได้กล่าวไว้คุณอาจต้องการไฟล์ json ในระบบที่คุณรู้ว่าปลอดภัยและมีอยู่เช่นไฟล์กำหนดค่า:

var objectFromRequire = require('path/to/my/config.json'); 

หรือใช้วัตถุโกลบอล JSON เพื่อแยกค่าสตริงลงในวัตถุ:

var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);

โปรดทราบว่าเมื่อคุณต้องการไฟล์เนื้อหาของไฟล์นั้นจะได้รับการประเมินซึ่งจะมีความเสี่ยงด้านความปลอดภัยในกรณีที่ไม่ใช่ไฟล์ json แต่เป็นไฟล์ js

ที่นี่ฉันได้เผยแพร่ตัวอย่างที่คุณสามารถดูทั้งสองวิธีและเล่นกับพวกเขาออนไลน์ (ตัวอย่างการแยกวิเคราะห์อยู่ในไฟล์ app.js - จากนั้นคลิกที่ปุ่มเรียกใช้และดูผลลัพธ์ในเทอร์มินัล): http: // staging1 .codefresh.io / ห้องปฏิบัติการ / API / env / JSON-แยกตัวอย่างเช่น

คุณสามารถแก้ไขรหัสและดูผลกระทบ ...


5

ใช้ JSON สำหรับการกำหนดค่าของคุณด้วย Node.js หรือไม่ อ่านและรับทักษะการตั้งค่าของคุณมากกว่า 9000 ...

หมายเหตุ: ผู้ที่อ้างว่า data = ต้องการ ('./ data.json'); เป็นความเสี่ยงด้านความปลอดภัยและ downvoting คำตอบของผู้คนที่มีความกระตือรือร้นกระตือรือร้น: คุณตรงและสมบูรณ์ที่ไม่ถูกต้อง ลองวางไม่ใช่ JSON ในแฟ้มที่ ... โหนดจะให้ข้อผิดพลาดตรงเหมือนมันจะถ้าคุณทำสิ่งเดียวกันกับมากช้าและยากที่จะคู่มือรหัสไฟล์อ่านแล้วภายหลัง JSON.parse () โปรดหยุดการเผยแพร่ข้อมูลที่ผิด คุณกำลังทำร้ายโลก แต่ไม่ได้ช่วยอะไร โหนดถูกออกแบบมาเพื่อให้สิ่งนี้; มันไม่ใช่ความเสี่ยงด้านความปลอดภัย!

แอปพลิเคชันที่เหมาะสมมีการกำหนดค่า3 เลเยอร์ :

  1. การกำหนดค่าเซิร์ฟเวอร์ / คอนเทนเนอร์
  2. แอปพลิเคชั่น config
  3. (ไม่บังคับ) การกำหนดค่าของผู้เช่า / ชุมชน / องค์กร
  4. กำหนดค่าผู้ใช้

นักพัฒนาซอฟต์แวร์ส่วนใหญ่ปฏิบัติต่อการกำหนดค่าเซิร์ฟเวอร์และแอพราวกับว่ามันสามารถเปลี่ยนแปลงได้ มันไม่สามารถ คุณสามารถชั้นการเปลี่ยนแปลงจากชั้นที่สูงขึ้นด้านบนของแต่ละอื่น ๆ แต่คุณกำลังปรับเปลี่ยนความต้องการของฐาน บางสิ่งจำเป็นต้องมีอยู่! ทำให้การกำหนดค่าของคุณทำตัวเหมือนมันไม่เปลี่ยนรูปเพราะโดยพื้นฐานแล้วบางอย่างก็เหมือนกับซอร์สโค้ดของคุณ

หากไม่เห็นว่าสิ่งของจำนวนมากของคุณจะไม่เปลี่ยนแปลงหลังจากเริ่มต้นนำไปสู่รูปแบบการต่อต้านเช่นการทิ้งขยะการกำหนดค่าของคุณด้วยการลองบล็อก / และบล็อกคุณสามารถดำเนินการต่อได้โดยไม่ต้องติดตั้งแอปพลิเคชัน คุณทำไม่ได้ หากเป็นเช่นนั้นนั่นเป็นของเลเยอร์การกำหนดค่าชุมชน / ผู้ใช้ไม่ใช่เลเยอร์การกำหนดค่าเซิร์ฟเวอร์ / แอป คุณกำลังทำผิด สิ่งที่เป็นตัวเลือกควรอยู่ด้านบนเมื่อแอปพลิเคชันเสร็จสิ้นเป็น bootstrap

หยุดการต่อสู้หัวของคุณกับผนัง: การตั้งค่าของคุณควรจะเรียบง่ายเป็นพิเศษ

ลองดูว่าการติดตั้งบางอย่างมีความซับซ้อนเช่นเดียวกับกรอบการบริการโปรโตคอล - ผู้ไม่เชื่อเรื่องพระเจ้าและผู้ให้ข้อมูล - ผู้ไม่เชื่อเรื่องพระเจ้าโดยใช้ไฟล์ json config ที่เรียบง่ายและไฟล์ app.js ง่าย ...

ภาชนะ config.js ...

{
    "service": {
        "type"  : "http",
        "name"  : "login",
        "port"  : 8085
    },
    "data": {
        "type"  : "mysql",
        "host"  : "localhost",
        "user"  : "notRoot",
        "pass"  : "oober1337",
        "name"  : "connect"
    }
}

index.js ... (เอ็นจิ้นที่ให้พลังทุกอย่าง)

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 ... (รหัสที่สนับสนุนบริการผู้ไม่เชื่อเรื่องพระเจ้าของโปรโตคอลและแหล่งข้อมูลของคุณ)

module.exports = function(request, response){
    response.end('Responding to: ' + request.url);
}

เมื่อใช้รูปแบบนี้คุณสามารถโหลดสิ่งที่ชุมชนและผู้ใช้ตั้งค่าไว้ด้านบนของแอพที่บู๊ตแล้ว dev dev พร้อมที่จะดันงานของคุณลงในที่เก็บและขยายขนาด คุณกำลังอ่านสำหรับหลายคน Userland ถูกแยกออก ตอนนี้คุณสามารถแยกข้อกังวลของโพรโทคอลบริการที่คุณใช้อยู่ซึ่งเป็นประเภทฐานข้อมูลที่คุณใช้อยู่และเพียงเน้นการเขียนโค้ดที่ดี

เนื่องจากคุณกำลังใช้เลเยอร์คุณสามารถพึ่งพาแหล่งความจริงเพียงแหล่งเดียวสำหรับทุกสิ่งได้ตลอดเวลา (วัตถุการกำหนดค่าแบบเลเยอร์) และหลีกเลี่ยงการตรวจสอบข้อผิดพลาดทุกขั้นตอนกังวลเกี่ยวกับ "โอ้อึฉันจะทำสิ่งนี้อย่างไรทำงานโดยไม่มีการตั้งค่าที่เหมาะสม?!? "


4

ทางออกของฉัน:

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);
});

ขอบคุณ @eloyesp ฉันพยายามใช้รหัสนี้ แต่ฉันได้รับTypeError: path must be a string or Bufferข้อผิดพลาด - ความคิดใดที่จะเริ่มแก้ไขปัญหานี้
GPP

4

แค่ต้องการทำคำตอบให้สมบูรณ์ (ขณะที่ฉันพยายามดิ้นรนซักครู่) ต้องการแสดงวิธีการเข้าถึงข้อมูล json ตัวอย่างนี้แสดงการเข้าถึง Json Array:

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);
  }
})


3

เพียงแค่ทำให้สิ่งนี้มีความซับซ้อนมากที่สุดและนำแพคเกจให้ได้มากที่สุด ...

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);

วิธีนี้ช่วยให้คุณ:

var dataPromise = readJsonFile("foo.json");
dataPromise.then(console.log);

หรือถ้าคุณใช้ async / คอย:

let data = await readJsonFile("foo.json");

ข้อได้เปรียบมากกว่าการใช้เพียงอย่างเดียวreadFileSyncคือเซิร์ฟเวอร์โหนดของคุณสามารถประมวลผลคำขออื่น ๆ ในขณะที่ไฟล์กำลังอ่านจากดิสก์


2

JSON.parse จะไม่รับรองความปลอดภัยของสตริง json ที่คุณแยกวิเคราะห์ คุณควรดูไลบรารีเช่นjson-safe-parseหรือไลบรารีที่คล้ายกัน

จากหน้า json-safe-parse npm:

JSON.parse ยอดเยี่ยม แต่มีข้อบกพร่องร้ายแรงหนึ่งข้อในบริบทของ JavaScript: ช่วยให้คุณสามารถแทนที่คุณสมบัติที่สืบทอดมา สิ่งนี้อาจกลายเป็นปัญหาหากคุณแยกวิเคราะห์ JSON จากแหล่งที่ไม่น่าเชื่อถือ (เช่นผู้ใช้) และการเรียกใช้ฟังก์ชันที่คุณคาดว่าจะมีอยู่


2

ใช้ฟังก์ชันความพยายามของ Lodash เพื่อส่งคืนวัตถุข้อผิดพลาดซึ่งคุณสามารถจัดการได้ด้วยฟังก์ชัน 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

3
คุณช่วยอธิบายได้ไหมว่าทำไมคุณจึงเพิ่ม.bindแทนที่จะใช้ _.attempt (JSON.parse, str)
steviejay

2

ตรวจสอบให้แน่ใจเสมอว่าใช้ JSON.parse ในการลอง catch block เนื่องจากโหนดจะโยนข้อผิดพลาดที่ไม่คาดคิดเสมอหากคุณมีข้อมูลที่เสียหายใน json ของคุณดังนั้นให้ใช้รหัสนี้แทนการใช้ JSON.Parse

try{
     JSON.parse(data)
}
catch(e){
   throw new Error("data is corrupted")
  }

1

หากคุณต้องการเพิ่มความคิดเห็นใน JSON ของคุณและอนุญาตให้ใช้จุลภาคต่อท้ายคุณอาจต้องการใช้ด้านล่าง implemention:

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);
}

โปรดทราบว่าอาจใช้งานไม่ได้หากคุณมีบางอย่าง"abc": "foo // bar"ใน JSON ดังนั้น YMMV


1

หากไฟล์ต้นฉบับ JSON ค่อนข้างใหญ่คุณอาจต้องการพิจารณาเส้นทางแบบอะซิงโครนัสผ่านวิธี async / await ดั้งเดิมที่มี Node.js 8.0 ดังนี้

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))

1

ผมใช้FS-พิเศษ ผมชอบมันมากเพราะ -although จะสนับสนุน callbacks- มันยังสนับสนุนสัญญา ดังนั้นมันช่วยให้ฉันสามารถเขียนรหัสของฉันในวิธีที่อ่านได้มากขึ้น:

const fs = require('fs-extra');
fs.readJson("path/to/foo.json").then(obj => {
    //Do dome stuff with obj
})
.catch(err => {
    console.error(err);
});

มันยังมีวิธีการที่มีประโยชน์มากมายซึ่งไม่ได้มาพร้อมกับfsโมดูลมาตรฐานและนอกจากนั้นมันยังเชื่อมโยงเมธอดจากfsโมดูลเนทิฟ

หมายเหตุ: คุณยังคงสามารถใช้วิธีการดั้งเดิมของ Node.js มีการแนะนำและคัดลอกไปยัง fs-extra ดูบันทึกเกี่ยวกับfs.read()&fs.write()

ดังนั้นมันจึงเป็นข้อดีทั้งหมด ฉันหวังว่าคนอื่นจะพบว่าสิ่งนี้มีประโยชน์


1

หากคุณต้องการที่จะแยก JSON กับ Node.js ในทางที่ปลอดภัย (aka: ข้อมูลผู้ใช้ป้อนสามารถหรือประชาชน API) ฉันขอแนะนำให้ใช้การรักษาความปลอดภัย-JSON-แจง

การใช้งานเป็นเหมือนค่าเริ่มต้นJSON.parseแต่จะป้องกันรหัสของคุณจาก:

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

0

คุณสามารถใช้ JSON.parse () (ซึ่งเป็นฟังก์ชันในตัวที่อาจบังคับให้คุณตัดคำด้วยคำสั่ง try-catch)

หรือใช้การแยกวิเคราะห์ไลบรารี JSON บางส่วนเช่นjson-parse-or



0

NodeJsเป็นเซิร์ฟเวอร์ที่ใช้JavaScriptดังนั้นคุณสามารถทำวิธีที่คุณทำในJavaScriptบริสุทธิ์...

ลองนึกภาพคุณมีJsonนี้ในNodeJs ...

var details = '{ "name": "Alireza Dezfoolian", "netWorth": "$0" }';
var obj = JSON.parse(details);

และคุณสามารถทำข้างต้นเพื่อรับ json แยกวิเคราะห์รุ่นของคุณ ...


0

ดังที่กล่าวไว้ในคำตอบข้างต้นเราสามารถใช้JSON.parse()ในการแยกสตริงเพื่อ JSON แต่ก่อนที่จะแยกวิเคราะห์ให้แน่ใจว่าได้แยกข้อมูลที่ถูกต้องหรืออื่น ๆ มันอาจทำให้ใบสมัครทั้งหมดของคุณลง

มีความปลอดภัยในการใช้งานเช่นนี้

let parsedObj = {}
try {
    parsedObj = JSON.parse(data);
} catch(e) {
    console.log("Cannot parse because data is not is proper json format")
}

0

JSON.parse(str);ใช้ อ่านข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ที่นี่

นี่คือตัวอย่างบางส่วน:

var jsonStr = '{"result":true, "count":42}';

obj = JSON.parse(jsonStr);

console.log(obj.count);    // expected output: 42
console.log(obj.result);   // expected output: true

-1

ไม่จำเป็นต้องมีโมดูลเพิ่มเติม
เพียงใช้
var parsedObj = JSON.parse(yourObj);
ฉันไม่คิดว่าจะมีปัญหาด้านความปลอดภัยเกี่ยวกับเรื่องนี้


-2

มันง่ายที่คุณสามารถแปลง JSON เพื่อสตริงใช้JSON.stringify(json_obj)และแปลงสตริง JSON JSON.parse("your json string")ใช้


2
คุณดูคำตอบที่ดีที่สุดสำหรับคำถามนี้หรือไม่? อายุ 3 ปีและสมบูรณ์มาก คุณคาดหวังอะไรที่จะมีส่วนร่วมกับข้อมูลเล็ก ๆ น้อย ๆ ที่คุณเสนอให้ที่นี่
Robby Cornelissen

2
ตอนนี้ตอนนี้เราไม่ต้องถือสองมาตรฐาน
danielmhanover
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.