ใช้ Node.JS ฉันจะอ่านไฟล์ JSON ลงในหน่วยความจำ (เซิร์ฟเวอร์) ได้อย่างไร


618

พื้นหลัง

ฉันกำลังทำการทดลองกับ Node.js และต้องการอ่านวัตถุ JSON ไม่ว่าจะเป็นไฟล์ข้อความหรือไฟล์. js (ที่ดีกว่า) ลงในหน่วยความจำเพื่อให้ฉันสามารถเข้าถึงวัตถุนั้นได้อย่างรวดเร็วจากโค้ด ฉันรู้ว่ามีสิ่งต่าง ๆ เช่น Mongo อัลเฟรด ฯลฯ ที่นั่น แต่นั่นไม่ใช่สิ่งที่ฉันต้องการในตอนนี้

คำถาม

ฉันจะอ่านอ็อบเจ็กต์ JSON จากไฟล์ข้อความหรือ js และในหน่วยความจำเซิร์ฟเวอร์โดยใช้ JavaScript / Node ได้อย่างไร?


1
สิ่งใดที่คุณเรียกหน่วยความจำเซิร์ฟเวอร์ สคริปต์ nodejs ของคุณจะทำงานตราบใดที่คุณใช้งานได้ แต่คุณจะต้องเก็บข้อมูลไว้ที่ใดที่หนึ่งเว้นแต่คุณจะทำให้สคริปต์ nodejs คงอยู่
mpm

คำตอบ:


1205

ซิงค์:

var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('file', 'utf8'));

async:

var fs = require('fs');
var obj;
fs.readFile('file', 'utf8', function (err, data) {
  if (err) throw err;
  obj = JSON.parse(data);
});

15
ฉันคิดว่า JSON.parse เป็นแบบซิงโครนัสโดยตรงจาก v8 ซึ่งหมายความว่าแม้จะมีวิธี Async คนก็ต้องระวังไฟล์ JSON ขนาดใหญ่ด้วย เนื่องจากมันจะเชื่อมโยงโหนด
Sean_A91

25
เพื่อความสมบูรณ์ มี npm ที่เรียกว่าjsonfileอยู่
สเตฟาน

5
ฉันไม่สามารถเชื่อว่ามันเป็นเรื่องยากที่จะหาสิ่งที่ง่าย คำตอบที่ผมได้จาก Google ทุกคนถูกทำ HttpRequest หรือใช้ JQuery หรือทำในเบราว์เซอร์
juliangonzalez

6
สองจุด: (1) let imported = require("file.json")คำตอบที่ซิงโครก็ควรจะเป็น (2) JSON.parse ต้องไม่ตรงกันเนื่องจากฉันใช้รหัสนี้เพื่อโหลดไฟล์ JSON ขนาด 70mb ลงในหน่วยความจำเป็นวัตถุ มันต้องใช้เวลามิลลิวินาทีวิธีนี้ แต่ถ้าผมใช้require()มันchugs
Kyle Baker

8
สำหรับผู้ที่ค้นหาคำตอบนี้ในปี 2562 เป็นต้นไป Node.js ได้ให้การสนับสนุน json ดั้งเดิมสำหรับหลาย ๆ รุ่นผ่านทางrequireคำตอบนี้ไม่สามารถใช้งานได้อีกต่อไปหากคุณต้องการโหลดไฟล์ json เพียงแค่ใช้let data = require('./yourjsonfile.json')และปิดการใช้งาน(พร้อมกับหนังสือว่าหากประสิทธิภาพของความต้องการกำลังส่งผลกระทบต่อโค้ดของคุณคุณจะมีปัญหาเกินกว่า "ต้องการโหลดไฟล์. json")
Mike 'Pomax' Kamermans

392

วิธีที่ง่ายที่สุดที่ฉันได้พบคือการใช้requireและเส้นทางไปยังไฟล์ JSON ของคุณ

ตัวอย่างเช่นสมมติว่าคุณมีไฟล์ JSON ต่อไปนี้

test.json

{
  "firstName": "Joe",
  "lastName": "Smith"
}

จากนั้นคุณสามารถโหลดได้อย่างง่ายดายในแอปพลิเคชัน node.js require

var config = require('./test.json');
console.log(config.firstName + ' ' + config.lastName);

35
มีคนรู้และถ้าฉันจำได้อย่างถูกต้องrequireในโหนดทำงานพร้อมกัน ดำน้ำลึกที่นี่
prasanthv

@Ram มันใช้งานได้สำหรับฉันอาจเป็นที่ตั้งของคุณtest.jsonจะแตกต่างจากตัวอย่างของเขา ฉันใช้node 5.0
guleria

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

13
"ต้องการ" หมายถึงใช้เพื่อโหลดโมดูลหรือไฟล์กำหนดค่าที่คุณใช้ตลอดอายุการใช้งานของแอปพลิเคชันของคุณ ดูเหมือนจะไม่ถูกต้องที่จะใช้สิ่งนี้เพื่อโหลดไฟล์
Yaki Klein

2
ฉันว่านี่อาจเป็นภัยคุกคามความปลอดภัย หากไฟล์ json ที่คุณกำลังโหลดมีรหัส JS จะrequireสามารถเรียกใช้รหัสนั้นได้หรือไม่ ถ้าเป็นเช่นนั้นคุณต้องควบคุมว่าไฟล์ json ของคุณมาจากไหนหรือผู้โจมตีสามารถเรียกใช้รหัสที่เป็นอันตรายบนเครื่องของคุณได้
sokkyoku

57

อะซิงโครนัสมีเหตุผล! ขว้างก้อนหินใส่ @mihai

มิฉะนั้นนี่คือรหัสที่เขาใช้กับเวอร์ชันอะซิงโครนัส:

// Declare variables
var fs = require('fs'),
    obj

// Read the file and send to the callback
fs.readFile('path/to/file', handleFile)

// Write the callback function
function handleFile(err, data) {
    if (err) throw err
    obj = JSON.parse(data)
    // You can now play with your datas
}

9
ตกลง :) เพิ่ม async ด้วย
mihai

1
ดีมาก :-) ฉันไม่ชอบการโทรกลับแบบอินไลน์ แต่มันอาจนำไปสู่ฝันร้ายของการติดต่อกลับที่ฉันควรหลีกเลี่ยง
Florian Margaine

9
มันมีเหตุผล .. เว้นแต่คุณต้องการซิงโครนัส
Matt Stephens

40

อย่างน้อยใน Node v8.9.1 คุณสามารถทำได้

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

และเข้าถึงองค์ประกอบทั้งหมดของวัตถุ JSON


5
วิธีนี้โหลดไฟล์เพียงครั้งเดียว หากคุณจะเปลี่ยนข้อมูลfile.jsonหลังจากที่ต้องการ (โดยไม่ต้องเริ่มโปรแกรมใหม่) จะมาจากการโหลดครั้งแรก ฉันไม่มีแหล่งที่จะสนับสนุนสิ่งนี้ แต่ฉันมีสิ่งนี้ในแอปที่ฉันกำลังสร้าง
Lukas Ignatavičius

คำตอบของคุณไม่สมบูรณ์ละห้อย สิ่งที่ทำให้คุณได้รับคือวัตถุและมันก็ไม่ได้กังวลที่จะใช้ tostring ()
David A. Gray

3
@ DavidA.Gray คำถามต้องการให้สามารถเข้าถึงวัตถุเป็นวัตถุไม่ใช่สตริง นอกเหนือจากปัญหาซิงเกิล Lukas ที่กล่าวถึงคำตอบนี้ใช้ได้
mikemaccana

2
การใช้ require จะเรียกใช้งานโค้ดที่กำหนดเองในไฟล์ วิธีนี้ไม่ปลอดภัยและฉันอยากจะแนะนำกับมัน
spoulson

16

ในโหนด 8 คุณสามารถใช้บิวด์อินutil.promisify()เพื่ออ่านไฟล์แบบนี้แบบอะซิงโครนัส

const {promisify} = require('util')
const fs = require('fs')
const readFileAsync = promisify(fs.readFile)

readFileAsync(`${__dirname}/my.json`, {encoding: 'utf8'})
  .then(contents => {
    const obj = JSON.parse(contents)
    console.log(obj)
  })
  .catch(error => {
    throw error
  })

3
.readFileที่มีอยู่แล้ว async .readFileSyncถ้าคุณกำลังมองหารุ่นซิงค์ชื่อของมันคือ
Aternus

หากคุณต้องการใช้สัญญานอกจากนี้ยังมีfs/promisesณ โหนด 10 หมายเหตุ: API ทดลองใช้: nodejs.org/api/fs.html#fs_fs_promises_api
aboutaaron

@Aternus .readFileคือไม่ตรงกันasyncแต่ไม่ ความหมายฟังก์ชันไม่ได้ถูกกำหนดด้วยasyncคำหลักและไม่ส่งคืนสัญญาดังนั้นคุณจึงไม่สามารถทำได้await fs.readFile('whatever.json');
Kip

@Kip วิธีการเกี่ยวกับ CodeSandBox?
Aternus

7

ใช้node-fs-extra (async กำลังรอ)

const readJsonFile = async () => {
  try {
    const myJsonObject = await fs.readJson('./my_json_file.json');
    console.log(myJsonObject);
  } catch (err) {
    console.error(err)
  }
}

readJsonFile() // prints your json object

6

การใช้แพ็คเกจfs-extraนั้นค่อนข้างง่าย:

ซิงค์:

const fs = require('fs-extra')

const packageObj = fs.readJsonSync('./package.json')
console.log(packageObj.version) 

async:

const fs = require('fs-extra')

const packageObj = await fs.readJson('./package.json')
console.log(packageObj.version) 

3
function parseIt(){
    return new Promise(function(res){
        try{
            var fs = require('fs');
            const dirPath = 'K:\\merge-xml-junit\\xml-results\\master.json';
            fs.readFile(dirPath,'utf8',function(err,data){
                if(err) throw err;
                res(data);
        })}
        catch(err){
            res(err);
        }
    });
}

async function test(){
    jsonData = await parseIt();
    var parsedJSON = JSON.parse(jsonData);
    var testSuite = parsedJSON['testsuites']['testsuite'];
    console.log(testSuite);
}

test();

2

https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_readfile_file_options_callback

var fs = require('fs');  

fs.readFile('/etc/passwd', (err, data) => {
  if (err) throw err;
  console.log(data);
});  

// options
fs.readFile('/etc/passwd', 'utf8', callback);

https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_readfilesync_file_options

คุณสามารถค้นหาการใช้งาน Node.js ทั้งหมดได้ที่ File System docs!
หวังว่าความช่วยเหลือนี้สำหรับคุณ!


0

คำตอบมากมายและไม่มีใครสร้างมาตรฐานเพื่อเปรียบเทียบการซิงค์กับอะซิงก์และการต้องการ ผมอธิบายความแตกต่างในกรณีการใช้งานของการอ่าน JSON ในหน่วยความจำผ่านต้องการ readFileSync และ readfile ที่นี่


-1

หากคุณกำลังมองหาโซลูชันที่สมบูรณ์สำหรับการAsyncโหลดไฟล์ JSON จากRelative Pathด้วยการจัดการข้อผิดพลาด

  // Global variables
  // Request path module for relative path
    const path = require('path')
  // Request File System Module
   var fs = require('fs');


// GET request for the /list_user page.
router.get('/listUsers', function (req, res) {
   console.log("Got a GET request for list of users");

     // Create a relative path URL
    let reqPath = path.join(__dirname, '../mock/users.json');

    //Read JSON from relative path of this file
    fs.readFile(reqPath , 'utf8', function (err, data) {
        //Handle Error
       if(!err) {
         //Handle Success
          console.log("Success"+data);
         // Parse Data to JSON OR
          var jsonObj = JSON.parse(data)
         //Send back as Response
          res.end( data );
        }else {
           //Handle Error
           res.end("Error: "+err )
        }
   });
})

โครงสร้างไดเรกทอรี:

ป้อนคำอธิบายรูปภาพที่นี่

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