Загрузить локальный файл JSON в переменную

113

Я пытаюсь загрузить файл .json в переменную в javascript, но не могу заставить его работать. Вероятно, это небольшая ошибка, но я не могу ее найти.

Все работает нормально, когда я использую такие статические данные:

var json = {
  id: "whatever",
  name: "start",
  children: [{
      "id": "0.9685",
      "name": " contents:queue"
    }, {
      "id": "0.79281",
      "name": " contents:mqq_error"
    }
  }]
}

Я поместил все, что находится {}в content.jsonфайле, и попытался загрузить это в локальную переменную JavaScript, как описано здесь: загрузить json в переменную .

var json = (function() {
  var json = null;
  $.ajax({
    'async': false,
    'global': false,
    'url': "/content.json",
    'dataType': "json",
    'success': function(data) {
      json = data;
    }
  });
  return json;
})();

Я запускал его с помощью отладчика Chrome, и он всегда сообщает мне, что значение переменной jsonравно null. В content.jsonфайл находится в том же каталоге, что и файл .js , который вызывает его.

Что я пропустил?

PogoMips
источник
1
URL-адрес вашего файла /content.jsonозначает, что файл находится на корневом уровне вашего веб-приложения. Измените на content.json(без косой черты), чтобы указать его в том же каталоге, где находится ваш файл сценария. Только в том случае, если ваш файл скрипта находится в каталоге корневого уровня, он будет работать.
Samich
файл находится в WebContent \ jit \ content.json .. Я попробовал 'url': "/WebContent/jit/content.json", но по-прежнему значение переменной равно нулю
PogoMips

Ответы:

38

Если вы вставили свой объект content.jsonнапрямую, это недействительный JSON. Ключи и значения JSON должны быть заключены в двойные кавычки ( "не '), если значение не является числовым, логическим nullили составным (массив или объект). JSON не может содержать функции или undefinedзначения. Ниже ваш объект как действительный JSON.

{
  "id": "whatever",
  "name": "start",
  "children": [
    {
      "id": "0.9685",
      "name": " contents:queue"
    },
    {
      "id": "0.79281",
      "name": " contents:mqq_error"
    }
  ]
}

У вас тоже была доп }.

Кевин Б.
источник
1
Я не могу поверить, что это исправлено ... почему он будет работать напрямую в файле .js без двойных кавычек, но не в файле .json? В этом нет никакого смысла ...
PogoMips
16
@ user1695165 - json и объект javascript - это разные вещи, они просто выглядят одинаково.
adeneo
2
@Kevin B "... если значение не является числовым [или логическим]."
Джейкоб Бошан
1
Просто совет: вы можете использовать валидатор json, например jsonlint.com , чтобы проверить свои данные json перед их использованием.
Марко Паничи
129

Мое решение, как здесь было сказано , заключается в использовании:

    var json = require('./data.json'); //with path

Файл загружается только один раз, дальнейшие запросы используют кеш.

edit Чтобы избежать кеширования, вот вспомогательная функция из этого сообщения в блоге, указанная в комментариях, с использованием fsмодуля:

var readJson = (path, cb) => {
  fs.readFile(require.resolve(path), (err, data) => {
    if (err)
      cb(err)
    else
      cb(null, JSON.parse(data))
  })
}
Эхвинс
источник
48
Просто хотел указать, что для этого решения требуется дополнительная библиотека с именем RequireJS .
Луис Кабонго
4
Как избежать кеширования?
Ноно
2
Не рекомендуется, по мнению Гильерме Оеннинга goenning.net/2016/04/14/stop-reading-json-files-with-require
Sangimed
2
TL; DR; кеширование поразило его в модульных тестах, и поэтому он дает вспомогательную функцию, чтобы избежать кеширования (ping @nono).
Ehvince
@Ehvince О, я этого не заметил, так как не прочитал всю статью. Спасибо :-)
Sangimed
51

Для ES6 / ES2015 вы можете импортировать напрямую, например:

// example.json
{
    "name": "testing"
}


// ES6/ES2015
// app.js
import * as data from './example.json';
const {name} = data;
console.log(name); // output 'testing'

Если вы используете Typescript, вы можете объявить модуль json, например:

// tying.d.ts
declare module "*.json" {
    const value: any;
    export default value;
}

Начиная с Typescript 2.9+ вы можете добавить - resolveJsonModule compilerOptions вtsconfig.json

{
  "compilerOptions": {
    "target": "es5",
     ...
    "resolveJsonModule": true,
     ...
  },
  ...
}
Little Roys
источник
5
импорт не работает в Chrome v72 - по-прежнемуUncaught SyntaxError: Unexpected token *
1000 Гбит / с
2
Когда я использую это, кажется, dataчто это модуль, но data.defaultэто объект
Дастин
1
Я пытался запустить это в консоли, но безуспешно. Это не работает с node v12.4.0, с babel-node 6.26.0. Я всегда получаюSyntaxError: Unexpected token *
mario199
2
для ES6 / ES2015 вы можете импортировать напрямую: кажется, что я получаю консольную ошибку при выполнении import * as data from './example.json'из-за ошибки типа mime.
Fallenreaper
если я использую import * as data from './example.json';then, dataэто просто модуль, но data.defaultэто объект. Но когда я использую import data from './example.json';то dataесть объект, который является более applicapable
Nel
4

Возможны две проблемы:

  1. AJAX является асинхронным, поэтому jsonбудет неопределенным при возврате из внешней функции. Когда файл загружен, функция обратного вызова установит jsonкакое-то значение, но в это время никого не волнует.

    Я вижу, что вы пытались исправить это с помощью 'async': false. Чтобы проверить, работает ли это, добавьте эту строку в код и проверьте консоль вашего браузера:

    console.log(['json', json]);
  2. Путь может быть неправильным. Используйте тот же путь, который вы использовали для загрузки вашего скрипта в HTML-документ. Итак, если ваш сценарий есть js/script.js, используйтеjs/content.json

    Некоторые браузеры могут показать вам, к каким URL-адресам они пытались получить доступ и как это было (коды успеха / ошибки, заголовки HTML и т. Д.). Проверьте средства разработки вашего браузера, чтобы узнать, что происходит.

Аарон Дигулла
источник
Может быть, его версия jquery еще не поддерживает это? Я улучшил формулировку.
Аарон Дигулла
4

Встроенный модуль node.js fs будет делать это асинхронно или синхронно в зависимости от ваших потребностей.

Вы можете загрузить его, используя var fs = require('fs');

Асинхронный

fs.readFile('./content.json', (err, data) => {
    if (err)
      console.log(err);
    else {
      var json = JSON.parse(data);
    //your code using json object
    }
})

Синхронный

var json = JSON.parse(fs.readFileSync('./content.json').toString());
Арно М.
источник
-1

Для данного формата json, как в файле ~ / my-app / src / db / abc.json:

  [
      {
        "name":"Ankit",
        "id":1
      },
      {
        "name":"Aditi",
        "id":2
      },
      {
        "name":"Avani",
        "id":3
      }
  ]

Порядок импорта в файл .js, например ~ / my-app / src / app.js:

 const json = require("./db/abc.json");

 class Arena extends React.Component{
   render(){
     return(
       json.map((user)=>
        {
          return(
            <div>{user.name}</div>
          )
        }
       )
      }
    );
   }
 }

 export default Arena;

Вывод:

Ankit Aditi Avani
Анк_247шбм
источник
Это ответ на вопрос, который здесь не задают.
Кевин Б.
@KevinB согласно моему объяснению, я импортировал файл .json в файл .js. Это помогло мне загрузить json-файл в const json. Отсюда я могу использовать следующий словарь json для атрибутов пользователя и так далее.
Ank_247shbm
Это здорово, однако, этот вопрос касается пользователя, пытающегося скопировать литерал объекта в файл .json, который затем загружается с помощью ajax, только его литерал объекта был в формате, который не действителен для JSON. При установке срабатывают и импорт этого с требуют, конечно , работать в некоторых случаях, это не помогает этот случай.
Кевин Б.
В качестве примечания: размещение комментариев со ссылками на этот ответ на все остальные ответы может рассматриваться как чрезмерная самореклама, а попытки редактировать ответы - вандализм. Ваши комментарии были удалены, пожалуйста, больше не вносите подобные изменения.
Брэд Ларсон