Sử dụng Node.JS, làm cách nào để đọc tệp JSON vào bộ nhớ (máy chủ)?


618

Lý lịch

Tôi đang thực hiện một số thử nghiệm với Node.js và muốn đọc một đối tượng JSON, từ tệp văn bản hoặc tệp .js (tốt hơn ??) vào bộ nhớ để tôi có thể truy cập nhanh vào đối tượng đó từ mã. Tôi nhận ra rằng có những thứ như Mongo, Alfred, v.v., nhưng đó không phải là thứ tôi cần ngay bây giờ.

Câu hỏi

Làm cách nào để đọc một đối tượng JSON ra khỏi tệp văn bản hoặc tệp js và vào bộ nhớ máy chủ bằng JavaScript / Node?


1
Bạn gọi bộ nhớ máy chủ là gì? tập lệnh nodejs của bạn sẽ hoạt động miễn là bạn làm cho nó hoạt động, nhưng bạn sẽ phải lưu trữ dữ liệu ở đâu đó trừ khi bạn duy trì tập lệnh nodejs.
mpm

Câu trả lời:


1205

Đồng bộ hóa:

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

Không đồng bộ:

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

15
Tôi nghĩ JSON.parse là đồng bộ, trực tiếp từ v8, có nghĩa là ngay cả với cách Async, mọi người phải cẩn thận với các tệp JSON lớn. vì nó sẽ buộc nút.
Sean_A91

25
Vì lợi ích của sự trọn vẹn. Họ tồn tại một npm được gọi là jsonfile .
Stefan

5
Tôi không thể tin rằng thật khó để tìm thấy điều đơn giản này. Mọi câu trả lời tôi nhận được từ google là thực hiện HTTPRequest hoặc sử dụng JQuery hoặc thực hiện nó trong trình duyệt
juliangonzalez

6
hai điểm: (1) Câu trả lời đồng bộ chỉ nên là let imported = require("file.json"). (2) JSON.parse phải không đồng bộ, vì tôi đã sử dụng mã này để tải tệp JSON 70mb vào bộ nhớ dưới dạng đối tượng. Phải mất một phần nghìn giây theo cách này, nhưng nếu tôi sử dụng require(), nó chu chu .
Kyle Baker

8
Đối với những người tìm thấy câu trả lời này vào năm 2019 trở đi, Node.js đã hỗ trợ json gốc cho nhiều, nhiều phiên bản require, với câu trả lời này không còn được áp dụng nếu bạn chỉ muốn tải tệp json. Chỉ cần sử dụng let data = require('./yourjsonfile.json')và tắt đi (với chú thích rằng nếu hiệu suất của yêu cầu ảnh hưởng đến mã của bạn, bạn sẽ gặp vấn đề lớn hơn là "muốn tải tệp .json")
Mike 'Pomax' Kamermans 11/2/19

392

Cách dễ nhất tôi đã tìm thấy để làm điều này là chỉ sử dụng requirevà đường dẫn đến tệp JSON của bạn.

Ví dụ: giả sử bạn có tệp JSON sau đây.

test.json

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

Sau đó, bạn có thể dễ dàng tải cái này trong ứng dụng node.js của mình bằng cách sử dụng require

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

35
Chỉ để mọi người biết, và nếu tôi nhớ chính xác, requiretrong nút chạy đồng bộ. Lặn sâu ở đây
prasanthv

@Ram Nó hoạt động với tôi có thể là vị trí của bạn test.jsonsẽ khác với ví dụ của anh ấy. Tôi đang sử dụngnode 5.0
guleria

18
Một vấn đề / lợi ích khác với phương pháp như vậy là thực tế là dữ liệu cần thiết được lưu trong bộ đệm trừ khi bạn xóa cụ thể bộ đệm được lưu trữ
magicode118

13
"Yêu cầu" có nghĩa là được sử dụng để tải các mô-đun hoặc tệp cấu hình bạn đang sử dụng trong suốt tuổi thọ của ứng dụng. dường như không đúng khi sử dụng điều này để tải tập tin.
Yaki Klein

2
Tôi muốn nói rằng đây có khả năng là một mối đe dọa an ninh. Nếu tệp json bạn đang tải chứa mã JS, liệu requirenó có chạy mã đó không? Nếu vậy thì bạn thực sự cần phải kiểm soát các tệp json của bạn đến từ đâu hoặc kẻ tấn công có thể chạy mã độc trên máy của bạn.
sokkyoku

57

Không đồng bộ là có lý do! Ném đá tại @mihai

Mặt khác, đây là mã anh ta đã sử dụng với phiên bản không đồng bộ:

// 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
đồng ý :), cũng đã thêm async
mihai

1
Tuyệt vời :-) Tôi không thích các cuộc gọi lại nội tuyến, điều đó có thể dẫn đến những cơn ác mộng gọi lại mà tôi muốn tránh.
Florian Margaine

9
Đó là vì một lý do .. trừ khi bạn muốn nó đồng bộ.
Matt Stephens

40

Ít nhất là trong Node v8.9.1, bạn chỉ có thể làm

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

và truy cập tất cả các phần tử của đối tượng JSON.


5
Cách tiếp cận này tải tập tin chỉ một lần. Nếu bạn sẽ thay đổi file.jsonsau khi yêu cầu mới (không khởi động lại chương trình), dữ liệu sẽ được tải lần đầu tiên. Tôi không có nguồn để sao lưu này, nhưng tôi đã có cái này trong ứng dụng tôi đang xây dựng
Lukas Ignatavičius

Câu trả lời của bạn là không đầy đủ. Những gì mang lại cho bạn là một đối tượng và thậm chí không bận tâm đến việc triển khai chuỗi ().
David A. Gray

3
@ DavidA.Gray Câu hỏi muốn có thể truy cập các đối tượng dưới dạng đối tượng, không phải dưới dạng chuỗi. Ngoài vấn đề singleton, Lukas đã đề cập câu trả lời này là ổn.
mikemaccana

2
Sử dụng yêu cầu cũng sẽ thực thi mã tùy ý trong tệp. Phương pháp này không an toàn và tôi khuyên bạn nên chống lại nó.
spoulson

16

Trong Nút 8, bạn có thể sử dụng util.promisify()tệp tích hợp để đọc không đồng bộ một tệp như thế này

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đã không đồng bộ, nếu bạn đang tìm phiên bản đồng bộ hóa, tên của nó là .readFileSync.
Aternus

Nếu bạn muốn sử dụng lời hứa, cũng có fs/promisestừ Nút 10. Lưu ý: API là thử nghiệm: nodejs.org/api/fs.html#fs_fs_promises_api
aboutaaron

@Aternus .readFilekhông đồng bộ , nhưng không phải async. Có nghĩa là, chức năng không được xác định bằng asynctừ khóa và cũng không trả lại Lời hứa, vì vậy bạn không thể thực hiệnawait fs.readFile('whatever.json');
Kip

@Kip làm thế nào về một CodeSandBox?
Aternus

7

sử dụng nút-fs-thêm (async await)

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

Sử dụng gói fs-Extra khá đơn giản:

Đồng bộ hóa:

const fs = require('fs-extra')

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

Không đồng bộ:

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

Bạn có thể tìm thấy tất cả việc sử dụng Node.js tại tài liệu Hệ thống tệp!
Hy vọng điều này sẽ giúp bạn!


0

Rất nhiều câu trả lời và không ai từng đưa ra một chuẩn để so sánh đồng bộ hóa với async so với yêu cầu. Tôi đã mô tả sự khác biệt trong các trường hợp sử dụng đọc json trong bộ nhớ thông qua yêu cầu, readFileSync và readFile tại đây .


-1

Nếu bạn đang tìm kiếm một giải pháp hoàn chỉnh để Asynctải tệp JSON từ Relative PathXử lý lỗi

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

Cấu trúc thư mục:

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.