Как получить доступ к содержимому файла JSON без ключа? - PullRequest
0 голосов
/ 13 июня 2018

По сути, я настраиваю веб-сервер через Node.js и Express (я новичок в этом) для получения данных путем чтения файла JSON.Например, это мой файл data.json:

[{
        "color": "black",
        "category": "hue",
        "type": "primary"
    },
    {
        "color": "red",
        "category": "hue",
        "type": "primary"
    }
]

Я пытаюсь получить все цвета, применяя этот код для отображения на локальном хосте:

router.get('/colors', function (req, res) {
    fs.readFile(__dirname + '/data.json', 'utf8', function (err, data) {
        data = JSON.parse(data);
        res.json(data); //this displays all of the contents of data.json
    })
});

router.get('/colors:name', function (req, res) {
    fs.readFile(__dirname + '/data.json', 'utf8', function (err, data) {
        data = JSON.parse(data);
        for (var i = 0; i < data.length; i++) {
            res.json(data[i][1]); //trying to display the values of color
        }
    })
});

Какмне делать это?

Ответы [ 6 ]

0 голосов
/ 13 июня 2018

Вы никогда не должны использовать fs.readFileSync в производстве.Любая функция синхронизации будет блокировать цикл обработки событий до тех пор, пока выполнение не будет завершено, что отсрочит все последующие слова (используйте с осторожностью, если сочтете необходимым) .Несколько дней назад я сам испытал наихудший опыт и усвоил это трудно.

В экспрессе вы можете определить маршрут с помощью param или query и использовать его для map содержимого внутри fs.readFile функция обратного вызова.

/** 
* get color by name
* 
* @param {String} name name of the color
* @return {Array} array of the color data matching param
*/

router.get('/colors/:name', (req, res) => {
    const color = req.params.name

    const filename = __dirname + '/data.json';

    fs.readFile('/etc/passwd', 'utf8', (err, data) => {
        if(err){
            return res.send([]); // handle any error returned by readFile function here
        }

        try{
            data = JSON.parse(data); // parse the JSON string to array

            let filtered = []; // initialise empty array

            if(data.length > 0){ // we got an ARRAY of objects, right? make your check here for the array or else any map, filter, reduce, forEach function will break the app
                filtered = data.filter((obj) => {
                    return obj.color === color; // return the object if the condition is true
                });
            }

            return res.send(filtered); // send the response 

    }
    catch(e){
      return res.send([]); // handle any error returned from JSON.parse function here
    }
  });

});

Для подведения итогов используйте асинхронную функцию fs.readFile, чтобы цикл событий не был засорен.Внутри обратного вызова проанализируйте содержимое, а затем return ответ.return действительно важно, иначе вы можете получить Ошибка: невозможно установить заголовки после их отправки

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ Данный код не протестирован, но долженРабота.Это просто для демонстрации идеи.

0 голосов
/ 13 июня 2018

То, что вы пытаетесь сделать, на самом деле довольно просто, если разбить его на более мелкие задачи.Вот один из способов его разбить:

  1. Загрузить данные JSON в память для использования вашим API.
  2. Определить маршрут API, который извлекает только цвета из ваших данных JSON иотправляет их клиенту в виде JSON.

var data = [];
try {
    data = JSON.parse(fs.readFileSync('/path/to/json'));
} catch (e) {
    // Handle JSON parse error or file not exists error etc
    data = [{
            "color": "black",
            "category": "hue",
            "type": "primary"
        },
        {
            "color": "red",
            "category": "hue",
            "type": "primary"
        }
    ]
}

router.get('/colors', function (req, res, next) {
    var colors = data.map(function (item) {
        return item.color
    }); // This will look look like: ["black","red"]
    res.json(colors); // Send your array as a JSON array to the client calling this API
})

Некоторые улучшения в этом методе:

  1. Файл читается только один раз синхронно, когда приложениезапущен и данные кэшируются в памяти для будущего использования.
  2. Использование Array.prototype.map Документов для извлечения массива цветов из объекта.

Примечание:

Вы можете структурировать массив цветов так, как вам нравится, и отправить его в виде JSON в этой структуре.

Примеры:

var colors = data.map(function(item){return {color:item.color};}); // [{"color":"black"},{"color":"red"}]

var colors = {colors: data.map(function(item){return item.color;})} // { "colors" : ["black" ,"red"] }

Некоторые ошибки в вашем коде:

  1. Вы используете res.json в цикле for, что неверно, так как ответ должен быть отправлен только один раз.В идеале вы должны построить объект JS в нужной вам структуре, перебирая свои данные и отправляя завершенный объект один раз с res.json (который, как я догадываюсь, внутренне JSON.stringify s), и отправляет его в качестве ответа после установкиправильные заголовки)
  2. Чтение файлов - дорогостоящая операция.Если вы можете позволить себе прочитать его один раз и кэшировать эти данные в памяти, это будет эффективно (при условии, что ваши данные не слишком велики - в этом случае использование файлов для хранения информации может быть неэффективным с самого начала)
0 голосов
/ 13 июня 2018

Если вы не хотите использовать клавиши в json, вы можете использовать функцию Object.values.

...
data = JSON.parse(data)
var values = []
for (var i = 0; i < data.length; i++) {
    values.push(Object.values(data[i])[0]) // 0 - color, 1 - category, 2 - type
}
res.json(values) // ["black","red"]
...
0 голосов
/ 13 июня 2018

в экспрессе вы можете сделать таким образом

router.get('/colors/:name', (req, res) => {
  const key = req.params.name
  const content = fs.readFileSync(__dirname + '/data.json', 'utf8')
  const data = JSON.parse(content)
  const values = data.reduce((values, value) => {
    values.push(value[key])
    return values      
  }, [])
  // values => ['black', 'red']
  res.send(values)
});

, а затем curl http://localhost/colors/color,
вы можете получить ['black', 'red']

0 голосов
/ 13 июня 2018

Я думаю, что вы не можете получить доступ к JSON без ключа.Вы можете использовать цикл Foreach для (var name: object) {} проверить, что foreach может вам помочь

0 голосов
/ 13 июня 2018

Что вы хотите сделать, это:

res.json(data[i]['color']);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...