92

I'm implementing an example from https://github.com/moroshko/react-autosuggest

Important code is like this:

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

This copy-paste code from the example (that works), has an error in my project:

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

If I take out the prefix json!:

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

This way I got not errors at compile time (import is done). However I got errors when I execute it:

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

If I debug it I can see suburbs is an objectc, not an array so filter function is not defined.

However in the example is commented suggestions is an array. If I rewrite suggestions like this, everything works:

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

So... what json! prefix is doing in the import?

Why can't I put it in my code? Some babel configuration?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
user2670996
  • 2,654
  • 6
  • 29
  • 45
  • 2
    Please, please, please re-evaluate the chose answer this is actually want you're using ES6 modules. You don't need anything at all, just a JS that understands ES6 modules. https://stackoverflow.com/a/53878451/124486 – Evan Carroll Dec 21 '18 at 02:27

6 Answers6

166

First of all you need to install json-loader:

npm i json-loader --save-dev

Then, there are two ways how you can use it:

  1. In order to avoid adding json-loader in each import you can add to webpack.config this line:

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

    Then import json files like this

    import suburbs from '../suburbs.json';
    
  2. Use json-loader directly in your import, as in your example:

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

Note: In webpack 2.* instead of keyword loaders need to use rules.,

also webpack 2.* uses json-loader by default

*.json files are now supported without the json-loader. You may still use it. It's not a breaking change.

v2.1.0-beta.28

eouw0o83hf
  • 9,438
  • 5
  • 53
  • 75
Oleksandr T.
  • 76,493
  • 17
  • 173
  • 144
  • 1
    Thank you so much! The documentation for json-loader was actually showing the settings for webpack v2, so nothing worked for me (using v1!). So for all of you out there, use loaders, not rules! Plus, change 'use' inside that object to be 'loader', just like this answer! – nbkhope Feb 02 '17 at 21:27
  • 5
    As @alexander-t mentioned, you can now import json files without the json-loader, but, if you run into an issue where the json-loader is not recognized, you should just add a '-loader' suffix in the loaders config like this: `{ test: /\.json$/, loader: 'json-loader' }` – cvetanov Feb 25 '17 at 10:52
  • Why doesn't the imported json get copied into outDir if it's being imported via typescript? – Blue Sep 13 '17 at 15:26
  • What if you don't have a `webpack.config`? – Benur21 Jun 14 '22 at 22:48
20

json-loader doesn't load json file if it's array, in this case you need to make sure it has a key, for example

{
    "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
  • 9,204
  • 15
  • 76
  • 121
10

This just works on 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
  • 701
  • 8
  • 11
4

With json-loader installed, now you can simply use:

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

or, even more simply:

import suburbs from '../suburbs';
Let Me Tink About It
  • 15,156
  • 21
  • 98
  • 207
2

Node v8.5.0+

You don't need JSON loader. Node provides ECMAScript Modules (ES6 Module support) with the --experimental-modules flag, you can use it like this

node --experimental-modules myfile.mjs

Then it's very simple

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

Then you'll have it bound to the variable myJSON.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
0

Found this thread when I couldn't load a json-file with ES6 TypeScript 2.6. I kept getting this error:

TS2307 (TS) Cannot find module 'json-loader!./suburbs.json'

To get it working I had to declare the module first. I hope this will save a few hours for someone.

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

...

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

If I tried to omit loader from json-loader I got the following error from webpack:

BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders. You need to specify 'json-loader' instead of 'json', see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed

Ogglas
  • 62,132
  • 37
  • 328
  • 418