52

I try to import a local .json-file using d3.json().

The file filename.json is stored in the same folder as my html file.

Yet the (json)-parameter is null.

d3.json("filename.json", function(json) {
    root = json;
    root.x0 = h / 2;
    root.y0 = 0;});
    . . . 
}

My code is basically the same as in this d3.js example

Belphegor
  • 4,456
  • 11
  • 34
  • 59
Aleks G
  • 740
  • 2
  • 8
  • 12
  • 1
    If you're using Chrome, you could try running it with `--disable-web-security`. – Lars Kotthoff Jun 20 '13 at 14:05
  • You can also run a local server on your machine and access the page that way. WAMP and MAMP both work great, or you can ever run from command line on a MAC: http://lifehacker.com/start-a-simple-web-server-from-any-directory-on-your-ma-496425450 – Chris Wilson Jun 20 '13 at 16:54
  • I should have just read the d3.json API a little more closely. Sorry for wasting people's time. – Aleks G Jun 21 '13 at 09:28
  • 1
    If you're using Chrome, the command line switch `--allow-file-access-from-files` is safer than `--disable-web-security`. – Kenny Evitt May 11 '16 at 15:20
  • possible root cause: http://stackoverflow.com/questions/4819060/allow-google-chrome-to-use-xmlhttprequest-to-load-a-url-from-a-local-file – Ciro Santilli OurBigBook.com Aug 03 '16 at 15:53

8 Answers8

57

If you're running in a browser, you cannot load local files.

But it's fairly easy to run a dev server, on the commandline, simply cd into the directory with your files, then:

python -m SimpleHTTPServer

(or python -m http.server using python 3)

Now in your browser, go to localhost:3000 (or :8000 or whatever is shown on the commandline).


The following used to work in older versions of d3:

var json = {"my": "json"};
d3.json(json, function(json) {
    root = json;
    root.x0 = h / 2;
    root.y0 = 0;
});
mb21
  • 34,845
  • 8
  • 116
  • 142
  • 1
    Can you please explain your code a bit... how would I go from this ```d3.json(filename, function(error, data) {...}``` (Should I submit a separate question?) – Ismail Moghul Oct 10 '14 at 23:13
  • 10
    I would say outright that this answer's code is wrong, except for the 13 upvotes. [d3.json](https://github.com/mbostock/d3/wiki/Requests#d3_json) takes a url as its first argument, not a json object. Ditto jQuery's [$.get](http://api.jquery.com/jQuery.get/) method. If the json is already defined in the file, there's no need to issue an ajax request via `d3.json` or `$.get`; simply reference the variable directly. Or am I missing something here that would explain the 13 upvotes? – James Conkling Sep 18 '15 at 01:31
  • @JamesConkling a variable isn't the same thing as a file. but yes, you can put the first line in my example in its own javascript file and that works as well. – mb21 Sep 18 '15 at 09:58
  • 2
    @mb21 yeah, that's my point, if the json is defined in the script file, why use `d3.json`? If the json is not defined in the script file, then use `d3.json` and load the script via a server. Mixing the two approaches (defining the json in the script file *and* using d3.json makes no sense at all). – James Conkling Sep 18 '15 at 18:50
  • @JamesConkling the question was about having the data in a JSON file (`{"my": "data"}`), not a script file (`var data = {"my": "data"};`) – mb21 Sep 20 '15 at 06:39
  • 2
    @mb21, yes, in which case `d3.json()` takes a string representing the path to the file. In *no* case should `d3.json()` take a JSON object (or anything other than a string) as its first argument. [see here](https://github.com/mbostock/d3/wiki/Requests). – James Conkling Sep 20 '15 at 18:29
  • it works for me. I have conda managed python 3. I run above on the anaconda prompt. – psangam Mar 04 '20 at 02:11
22

In version d3.v5, you should do it as

d3.json("file.json").then(function(data){ console.log(data)});

Similarly, with csv and other file formats.

You can find more details at https://github.com/d3/d3/blob/master/CHANGES.md

Nick
  • 138,499
  • 22
  • 57
  • 95
Manas
  • 888
  • 10
  • 20
  • Please use the `edit` link to add more information to your answer rather than a comment. I've done this for you on this post. – Nick Dec 18 '18 at 22:07
  • this works on an html, js file and json file. But I use this in Angular 7 and i get GET error. I use a json emitted from a service from a url I found, and it works. For some reason, local json files cant be used inside of d3.json(). – Gel Jul 07 '19 at 15:53
  • @Gel this should work in Angular if you put the json file in your assets folder – Matt Saunders May 18 '20 at 09:08
10

Adding to the previous answers it's simpler to use an HTTP server provided by most Linux/ Mac machines (just by having python installed).

Run the following command in the root of your project

python -m SimpleHTTPServer

Then instead of accessing file://.....index.html open your browser on http://localhost:8080 or the port provided by running the server. This way will make the browser fetch all the files in your project without being blocked.

bigsolom
  • 2,309
  • 1
  • 19
  • 15
7

Loading a local csv or json file with (d3)js is not safe to do. They prevent you from doing it. There are some solutions to get it working though. The following line basically does not work (csv or json) because it is a local import:

d3.csv("path_to_your_csv", function(data) {console.log(data) });

Solution 1: Disable the security in your browser

Different browsers have different security setting that you can disable. This solution can work and you can load your files. Disabling is however not advisable. It will make you vulnerable for all kind of threads. On the other hand, who is going to use your software if you tell them to manually disable the security?

Disable the security in Chrome:

--disable-web-security
--allow-file-access-from-files

Solution 2: Load your csv/json file from a website.

This may seem like a weird solution but it will work. It is an easy fix but can be unpractical though. See here for an example. Check out the page-source. This is the idea:

d3.csv("https://path_to_your_csv", function(data) {console.log(data) });

Solution 3: Start you own browser, with e.g. Python.

Such a browser does not include all kind of security checks. This may be a solution when you experiment with your code on your own machine. In many cases, this may not be the solution when you have users. This example will serve HTTP on port 8888 unless it is already taken:

python -m http.server 8888
python -m SimpleHTTPServer 8888 &

Open the (Chrome) browser address bar and type the underneath. This will open the index.html. In case you have a different name, type the path to that local HTML page.

localhost:8888

Solution 4: Use local-host and CORS

You may can use local-host and CORS but the approach is not user-friendly coz setting up this, may not be so straightforward.

Solution 5: Embed your data in the HTML file

I like this solution the most. Instead of loading your csv, you can write a script that embeds your data directly in the html. This will allow users use their favorite browser, and there are no security issues. This solution may not be so elegant because your html file can grow very hard depending on your data but it will work though. See here for an example. Check out the page-source.

Remove this line:

d3.csv("path_to_your_csv", function(data) { })

Replace with this:

var data = 
    [
        $DATA_COMES_HERE$
    ]
erdogant
  • 1,544
  • 14
  • 23
6

http://bl.ocks.org/eyaler/10586116 Refer to this code, this is reading from a file and creating a graph. I also had the same problem, but later I figured out that the problem was in the json file I was using(an extra comma). If you are getting null here try printing the error you are getting, like this may be.

d3.json("filename.json", function(error, graph) {
  alert(error)
})

This is working in firefox, in chrome somehow its not printing the error.

Surendra Pratap
  • 101
  • 2
  • 7
1

You can't readily read local files, at least not in Chrome, and possibly not in other browsers either.

The simplest workaround is to simply include your JSON data in your script file and then simply get rid of your d3.json call and keep the code in the callback you pass to it.

Your code would then look like this:

json = { ... };

root = json;
root.x0 = h / 2;
root.y0 = 0;
... 
Kenny Evitt
  • 9,291
  • 5
  • 65
  • 93
1

I have used this

d3.json("graph.json", function(error, xyz) {
    if (error) throw error;
    // the rest of my d3 graph code here
    }

so you can refer to your json file by using the variable xyz and graph is the name of my local json file

Aakanksha Choudhary
  • 515
  • 2
  • 5
  • 19
-1

Use resource as local variable

var filename = {x0:0,y0:0};
//you can change different name for the function than json
d3.json = (x,cb)=>cb.call(null,x); 
d3.json(filename, function(json) {
    root = json;
    root.x0 = h / 2;
    root.y0 = 0;});
    //...
}
Alex Szücs
  • 561
  • 5
  • 12