Implementacja modułów ES6, jak załadować plik json

87

Implementuję przykład z https://github.com/moroshko/react-autosuggest

Ważny kod wygląda tak:

import React, { Component } from 'react';
import suburbs from 'json!../suburbs.json';

function getSuggestions(input, callback) {
  const suggestions = suburbs
    .filter(suburbObj => suburbMatchRegex.test(suburbObj.suburb))
    .sort((suburbObj1, suburbObj2) =>
      suburbObj1.suburb.toLowerCase().indexOf(lowercasedInput) -
      suburbObj2.suburb.toLowerCase().indexOf(lowercasedInput)
    )
    .slice(0, 7)
    .map(suburbObj => suburbObj.suburb);

  // 'suggestions' will be an array of strings, e.g.:
  //   ['Mentone', 'Mill Park', 'Mordialloc']

  setTimeout(() => callback(null, suggestions), 300);
}

Ten kod kopiuj-wklej z przykładu (który działa) zawiera błąd w moim projekcie:

Error: Cannot resolve module 'json' in /home/juanda/redux-pruebas/components

Jeśli usunę prefiks json !:

import suburbs from '../suburbs.json';

W ten sposób nie otrzymałem błędów w czasie kompilacji (import jest zakończony). Jednak mam błędy, kiedy go wykonuję:

Uncaught TypeError: _jsonfilesSuburbsJson2.default.filter is not a function

Jeśli go debuguję, widzę, że przedmieścia to obiekt, a nie tablica, więc funkcja filtru nie jest zdefiniowana.

Jednak w przykładzie komentowane sugestie to tablica. Jeśli przepisuję sugestie w ten sposób, wszystko działa:

  const suggestions = suburbs
  var suggestions = [ {
    'suburb': 'Abbeyard',
    'postcode': '3737'
  }, {
    'suburb': 'Abbotsford',
    'postcode': '3067'
  }, {
    'suburb': 'Aberfeldie',
    'postcode': '3040'
  } ].filter(suburbObj => suburbMatchRegex.test(suburbObj.suburb))

Więc ... co json! prefiks robi podczas importu?

Dlaczego nie mogę umieścić tego w moim kodzie? Jakaś konfiguracja Babel?

user2670996
źródło
1
Proszę, proszę, ponownie oceń wybraną odpowiedź, tak naprawdę chcesz, abyś używał modułów ES6. Nie potrzebujesz niczego, wystarczy JS, który rozumie moduły ES6. stackoverflow.com/a/53878451/124486
Evan Carroll,

Odpowiedzi:

155

Przede wszystkim musisz zainstalować json-loader:

npm i json-loader --save-dev

Następnie możesz z niego skorzystać na dwa sposoby:

  1. Aby uniknąć dodawania json-loaderw każdym import, możesz dodać do webpack.configtej linii:

    loaders: [
      { test: /\.json$/, loader: 'json-loader' },
      // other loaders 
    ]
    

    Następnie zaimportuj jsontakie pliki

    import suburbs from '../suburbs.json';
    
  2. Użyj json-loaderbezpośrednio w swoim import, jak w przykładzie:

    import suburbs from 'json!../suburbs.json';
    

Uwaga: W webpack 2.*zamiast słowa kluczowego loaderstrzeba użyć rules,.

webpack 2.*używa również json-loaderdomyślnie

Pliki * .json są teraz obsługiwane bez modułu ładującego json. Nadal możesz go używać. To nie jest przełomowa zmiana.

v2.1.0-beta.28

Oleksandr T.
źródło
1
Dziękuję bardzo! Dokumentacja dla json-loader faktycznie pokazywała ustawienia dla webpacka v2, więc nic nie działało (używając v1!). Więc dla was wszystkich używajcie ładowarek, a nie reguł! Dodatkowo zmień „use” wewnątrz tego obiektu na „loader”, tak jak ta odpowiedź!
nbkhope
5
Jak wspomniał @ alexander-t, możesz teraz importować pliki json bez modułu ładującego json, ale jeśli napotkasz problem, w którym moduł ładujący json nie jest rozpoznawany, powinieneś po prostu dodać sufiks „-loader” w konfiguracji modułu ładującego w ten sposób:{ test: /\.json$/, loader: 'json-loader' }
cvetanov
Dlaczego zaimportowany plik json nie jest kopiowany do outDir, jeśli jest importowany za pomocą skryptu?
Goodbye StackExchange
17

json-loader nie ładuje pliku json, jeśli jest to tablica, w tym przypadku musisz upewnić się, że ma klucz, na przykład

{
    "items": [
    {
      "url": "https://api.github.com/repos/vmg/redcarpet/issues/598",
      "repository_url": "https://api.github.com/repos/vmg/redcarpet",
      "labels_url": "https://api.github.com/repos/vmg/redcarpet/issues/598/labels{/name}",
      "comments_url": "https://api.github.com/repos/vmg/redcarpet/issues/598/comments",
      "events_url": "https://api.github.com/repos/vmg/redcarpet/issues/598/events",
      "html_url": "https://github.com/vmg/redcarpet/issues/598",
      "id": 199425790,
      "number": 598,
      "title": "Just a heads up (LINE SEPARATOR character issue)",
    },
    ..... other items in array .....
]}
DmitrySemenov
źródło
Niezły, nie myślałem o tym!
Zachary Dahan
9

Działa to tylko na React i React Native

const data = require('./data/photos.json');

console.log('[-- typeof data --]', typeof data); // object


const fotos = data.xs.map(item => {
    return { uri: item };
});
Kiko Seijo
źródło
2

Po json-loaderzainstalowaniu możesz teraz po prostu użyć:

import suburbs from '../suburbs.json';

lub jeszcze prościej:

import suburbs from '../suburbs';
Pozwól mi się nad tym zastanowić
źródło
0

Znalazłem ten wątek, gdy nie mogłem załadować pliku json-filez ES6 TypeScript 2.6. Ciągle otrzymuję ten błąd:

TS2307 (TS) Nie można znaleźć modułu 'json-loader! ./ suburbs.json'

Aby to działało, musiałem najpierw zadeklarować moduł. Mam nadzieję, że to komuś zaoszczędzi kilka godzin.

declare module "json-loader!*" {
  let json: any;
  export default json;
}

...

import suburbs from 'json-loader!./suburbs.json';

Gdybym próbował pominąć loaderze json-loadermam następujący błąd z webpack:

PRZEŁOMOWA ZMIANA: Nie można już pomijać sufiksu „-loader” podczas korzystania z programów ładujących. Musisz określić „json-loader” zamiast „json”, zobacz https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed

Ogglas
źródło
0

Węzeł v8.5.0 +

Nie potrzebujesz modułu ładującego JSON. Węzeł zapewnia moduły ECMAScript (obsługa modułu ES6) z --experimental-modulesflagą, możesz jej używać w ten sposób

node --experimental-modules myfile.mjs

Wtedy jest to bardzo proste

import myJSON from './myJsonFile.json';
console.log(myJSON);

Wtedy będziesz mieć to powiązane ze zmienną myJSON.

Evan Carroll
źródło