Implementação de módulos ES6, como carregar um arquivo json

87

Estou implementando um exemplo de https://github.com/moroshko/react-autosuggest

O código importante é assim:

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

Este código de copiar e colar do exemplo (que funciona), tem um erro no meu projeto:

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

Se eu tirar o prefixo json !:

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

Desta forma não obtive erros em tempo de compilação (importação feita). No entanto, recebo erros ao executá-lo:

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

Se eu depurar, posso ver que suburbs é um objectc, não uma matriz, portanto a função de filtro não está definida.

No entanto, no exemplo comentado, as sugestões são uma matriz. Se eu reescrever sugestões como esta, tudo funciona:

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

Então ... o que json! prefixo está fazendo na importação?

Por que não posso colocá-lo no meu código? Alguma configuração de babel?

user2670996
fonte
1
Por favor, por favor, reavalie a resposta escolhida que você realmente quer, você está usando módulos ES6. Você não precisa de nada, apenas um JS que entende os módulos ES6. stackoverflow.com/a/53878451/124486
Evan Carroll

Respostas:

156

Em primeiro lugar, você precisa instalar json-loader:

npm i json-loader --save-dev

Então, existem duas maneiras de como você pode usá-lo:

  1. Para evitar adicionar json-loadercada um, importvocê pode adicionar a webpack.configesta linha:

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

    Em seguida, importe jsonarquivos como este

    import suburbs from '../suburbs.json';
    
  2. Use json-loaderdiretamente no seu import, como no seu exemplo:

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

Nota: Em webpack 2.*vez de palavra-chave, é loadersnecessário usar rules.,

também webpack 2.*usa json-loaderpor padrão

Arquivos * .json agora são suportados sem o json-loader. Você ainda pode usá-lo. Não é uma mudança significativa.

v2.1.0-beta.28

Oleksandr T.
fonte
1
Muito obrigado! A documentação do json-loader estava realmente mostrando as configurações do webpack v2, então nada funcionou para mim (usando v1!). Então, para todos vocês, use carregadores, não regras! Além disso, altere 'usar' dentro desse objeto para 'carregador', assim como esta resposta!
nbkhope
5
Como @ alexander-t mencionou, agora você pode importar arquivos json sem o json-loader, mas, se você tiver um problema em que o json-loader não é reconhecido, você deve apenas adicionar um sufixo '-loader' na configuração do carregador assim:{ test: /\.json$/, loader: 'json-loader' }
cvetanov
Por que o json importado não é copiado para outDir se está sendo importado por meio de typescript?
Adeus StackExchange
17

json-loader não carrega o arquivo json se for array, neste caso você precisa ter certeza de que tem uma chave, por exemplo

{
    "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
fonte
Legal, não pensei nisso!
Zachary Dahan
9

Isso só funciona no React & 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
fonte
2

Com json-loaderinstalado, agora você pode simplesmente usar:

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

ou, ainda mais simplesmente:

import suburbs from '../suburbs';
Deixe-me pensar sobre isso
fonte
0

Encontrei este tópico quando não consegui carregar um json-filecom ES6 TypeScript 2.6. Continuei recebendo este erro:

TS2307 (TS) Não é possível localizar o módulo 'json-loader! ./ suburbs.json'

Para fazê-lo funcionar, eu tive que declarar o módulo primeiro. Espero que isso economize algumas horas para alguém.

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

...

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

Se tentei omitir loaderem json-loader, obtive o seguinte erro de webpack:

QUEBRANDO A MUDANÇA: Não é mais permitido omitir o sufixo '-loader' ao usar carregadores. Você precisa especificar 'json-loader' em vez de 'json', consulte https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed

Ogglas
fonte
0

Node v8.5.0 +

Você não precisa do carregador JSON. Node fornece Módulos ECMAScript (suporte para Módulo ES6) com o --experimental-modulessinalizador, você pode usá-lo assim

node --experimental-modules myfile.mjs

Então é muito simples

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

Então você o terá vinculado à variável myJSON.

Evan Carroll
fonte