d3.js parse JSON-like data from file - javascript

I am struggling with reading in data from a JSON file.
The JSON file that I want to read has the following structure:
{"name":"Andy Hunt",
"title":"Big Boss",
"age": 68,
"bonus": true
}
{"name":"Charles Mack",
"title":"Jr Dev",
"age":24,
"bonus": false
}
However, as far as I understand, d3.js can only parse JSON arrays that have the following structure:
[
{"name":"Andy Hunt",
"title":"Big Boss",
"age": 68,
"bonus": true
},
{"name":"Charles Mack",
"title":"Jr Dev",
"age":24,
"bonus": false
}
]
I am using this code snippet trying to display the first data object just to see if it works:
d3.json("/data/sample_data.json", function(data) {
console.log(data[0]);
});
This works for the second JSON structure, but not for the first one.
Now my question: Is it possible to somehow read in data with d3.js?
Or do I have to write a program, that reformats the whole JSON file as a JSON array?
EDIT: Turns out the data I wanted to use was formatted as NDJSON. So there is currently no way to read the data natively with d3.js other than parsing it as text and reformat it on the go the way #Mark explained.

As #Shashank points out your JSON is simply invalid. This has nothing to do with d3 but rather JavaScript and acceptable JSON formats. So, how can we fix it? You could do it in your d3/javascript itself instead of pre-processing the files.
// how many lines of JSON make an object?
var chunks = 5,
data = [];
//download file as TEXT
d3.text("data.txt", function(error, text) {
if (error) throw error;
// split on new line
var txt = text.split("\n");
// iterate it
for (var i = 0; i < txt.length; i += chunks) {
var block = "";
// grab blocks of 5 lines
for (var j = 0; j < chunks; j++ ){
block += txt[i+j];
}
// parse as JSON and push into data ARRAY
data.push(JSON.parse(block));
}
console.log(data);
});
Here it is running on a plunker.

The format of the JSON file you're trying to read is incorrect. JSON (as per standards) can be a collection of name/value pairs i.e. an object OR a list of objects i.e. an array of objects. Refer this: http://json.org/
If you're JSON file has the following data (notice the format - a single object):
{
"name":"Andy Hunt",
"title":"Big Boss",
"age": 68,
"bonus": true,
"value": 500
}
d3.json will provide the following result:
=> {name: "Andy Hunt", title: "Big Boss", age: 68, bonus: true, value: 500}
You've already tried it with the array structure.
I'd suggest you to change the JSON file to an array of objects. Hope this clears it up.

Related

How to repalce HTML text with JSON data

Received data from api and converted into JSON format, however every time I try to change a selected element in HTML I get either undefined or Object Obejct.
I have tried JSON.parse/JSON.stringify. I have tried innerHTML, innerText, textContent. I have tried for loops.
HTML
<p id="lang">C++</p>
Javascript
let language = document.getElementById('lang');
let data = {
"book": [
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
}
]
};
data = JSON.stringify(data);
language.innerHTML = data.book.language;
Need C++ in paragraph tag to change to Java in data. If Jquery would make this easier I would appreciate knowing how that works as well.
Since the data model you presented has books as an array, you'll need to get that out this way
data.book[0].language
0 being the index of whatever book you want to display
data = {
"book": [
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
}
]
};
language.innerHTML = data.book[0].language;
This is not working as book is an array of objects, not a singular object. So you'd need to use data.book[0].language
P.S. You don't need to use JSON.stringify here, if you are receveing a JSON string from your API, you should use JSON.parse
Here is an example of the code running correctly:
https://jsfiddle.net/2et3zh7g/
From Mozilla
The JSON.stringify() method converts a JavaScript object or value to a JSON string
So it seems your code is going the opposite direction of your stated intent.
let data = {
"book": [
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
}
]
};
After which, data already contains an object.
data = JSON.stringify(data);
And now, data contains a string. So naturally, data.book will result in an undefined value.
If, however, you were to receive the data as actual JSON, such as
let dataJSON = '{"book":[{"id":"01","language":"Java","edition":"third","author":"Herbert Schildt"}]}';
You could then extract the language value using JSON.parse as follows:
let data = JSON.parse(dataJSON);
let bookLanguage = data.book[0].language;
language.innerText = bookLanguage;
Note the array subscript on book. Since in your example, it contains an array of objects, you need to be sure to subscript into it.

Append data acquired from JSON to a Raphael object

Solved the question on my own, see answer
Using jQuery 3.2.1 and Raphael 2.1.1, if this matters
In my Raphael .js I first create some objects without any data and push them into an array, e. g. (.attr omitted):
var objarr = [];
var obj1 = rsr.path("M ... z");
objarr.push(obj1);
After this, I want to take data from a JSON file (an array named "regions" of multiple entries that consist of multiple key-value pairs (validated through JSONLint) and append it as data by id. It looks like this:
{
"regions": [{
"id": "0",
"var1": "foo1",
"var2": "bar1",
},
{
"id": "1",
"var1": "foo2",
"var2": "bar2",
},
// And so on for every object
]
}
I use the following code (localhost is used because otherwise I get a cross-access error:
for (var i = 0; i < objarr.length; i++)
{
var jq = $.getJSON("http://localhost:8000/data.json",{id: +i},function(t){
console.log( "success" );
})
.done(function(objdata){
console.log("success2");
$.each(objdata.regions, function(key, val){
objarr[i].data(key,val);
});
})
.fail(function(t){
console.log("error");
})
.always(function(t){
console.log("complete");
});
}
The console gives me both successes, but after this I get an error "Cannot read property 'data' of undefined". alert(key) and alert(val) give 0 and [object Object] respectively for every call. I tried adding the following to .done:
var items = [];
$.each(objdata.regions, function(key, val){
items.push("id" + key + ":" + val);
console.log(items);
});
The result was a string that went ["id0:[object Object]"],["id0:[object Object]", "id1:[object Object]"] and so on until it had objarr.length ids, repeating the needed amount of times. If I add [i] to objdata.regions, I get no console messages about items[] content at all.
I also found two somewhat closely related questions ("1" and "2"), checked the jQuery documentation for .getJSON(); and Raphael documentation for Element.data();. I've tried the following to check validity of my calls:
console.log(objdata) in the beginning of .done -- returns full base object of JSON data
console.log(objdata.regions) in the beginning of .done -- returns array of objects of JSON data
console.log(objdata.regions[i]) in the beginning of .done -- returns undefined
console.log(objdata.regions[0]) in the beginning of .done -- returns first object (works for every object)
I've used objdata.regions[0] in the snippet with items[] and the adding seems to work properly (console shows the keys and values being added to the array). However, it still doesn't work with objarr[i].data(key,val) (as well as ""+key and "$key").
I have two questions:
1. How do I acquire the key-value pairs properly while looping?
2. How do I append these pairs as data to a Raphael object?
I moved the for loop inside .done() and everything is appended successfully:
.done(function(objdata){
for (var i = 0; i < objarr.length; i++)
{
console.log("success2");
$.each(objdata.regions[i],function(key, val){
objarr[i].data(key, val);
});
}
})

Accessing JSON nested via key with no value using Javascript / jQuery

I'm trying to return the values of JSON objects which are nested within a complex array of objects. Unfortunately I've not been able to do it easily as the structure of the JSON seems unusual; for example:
var cartContents = {
"contents":
{
"ed2be4abf6cc927dd670b567efd42fc3":
{
"id": "1288785070733722605",
"quantity":2,
"limit":10,
"offset":0,
"order":null,
"created_at":"2016-07-06 12:18:10",
"updated_at":"2016-07-06 12:18:34",
"sku":"006",
"title":"Fishing Rod",
"slug":"fishing-rod-lara-fluorescent-print",
"sale_price":0,
"status":{
"value":"Draft",
"data": {
"key":"0",
"value":"Draft"
}
},
"category":
{
"value":"Bottom",
"data":
{
"1228355758422329063":
{
"id":"1238352758122309063",
"order":null,
"created_at":"2016-07-06 11:23:54",
"updated_at":"2016-07-06 11:38:23",
"parent":
{
"value":"All Sports",
"data":
{
"id":"2288364532150634121",
"order":null,
"created_at":"2016-07-06 11:37:25"...
}
}
}
}
}
}
}
}
The following code produces the correct result ("Fishing Rod"):
var x = cartContents.contents;
console.log(x.ed2be4abf6cc927dd670b567efd42fc3.title);
However the whole point is that the 32 character string ('ed2be4abf6cc927dd670b567efd42fc3') represents one of many products, each with a random 32 bit string and therefore they can't be individually coded into the JS.
I've tried a very great deal of different ways. The latest is the following code (where 'carts' is an array of unique 32 character strings:
var x = cartContents.contents;
$.each(carts, function() {
console.log(x.this.title);
});
The result is "jQuery.Deferred exception: Cannot read property 'title' of undefined TypeError: Cannot read property 'title' of undefined".
Would greatly appreciate help accessing the following keys and their values:
"title":"Fishing Rod"
"id":"1238352758122309063"
"created_at":"2016-07-06 11:37:25"
Also worth mentioning that I can't touch the server, therefore I can't change the data structure at all.
Many thanks in advance.

NodeJs read JSON file

I am tying to read a json file using NodeJs
my code is pretty basic,
var obj = require("./sample.json");
console.log(obj[0]);
The sample.json file contains a stringified JSON like this,
"[{\"sample\":\"good\",\"val\":76159}]"
However the console.log output is '[' not the first element in the variable. I have tried opening the file in the long way like this as well.
var obj;
fs.readFile('sample.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data);
console.log(obj[0]);
});
But here also the output is '[' why is the json file not properly parsed? How can I fix it?
Thanks in advance.
Your file should contain:
[{"sample":"good","val":76159}]
If it contains
"[{\"sample\":\"good\",\"val\":76159}]"
Then it is encoded twice. It is still valid JSON because it is a string, but this JSON does not represent the JavaScript Object:
[{
sample:"good",
val:76159
}]
But a string with the content [{"sample":"good","val":76159}].
If you add a second parse (the first one is implicitly done by the require):
var obj = JSON.parse(require("./sample.json"));
console.log(obj[0]);
then you will see that the the correct information is logged.
So your initial problem is that you stored the value the wrong way in ./sample.json.
[info.json]
[{
"name" : "Young",
"age" : 100,
"skill" : "js"
}]
[main.js]
var jsonObj = require('./info.json');
console.log(jsonObj[0]);
[result]
{ name: 'Young', age: 100, skill: 'js' }

Parse a JSON array into a javascript array

var jsonData = JSON.parse(pump_array);
var name_array = [];
var data_array = [];
for(var i=0;i<jsonData.pumps.length;i++)
{
data_array.push(data_array, pump_array.pumps[i].volume);
name_array.push(name_array, pump_array.pumps[i].iName);}
this is my javascript code. I am trying to parse out specific pieces of the following json array in order to place it into a graph using chart.js
var pump_array = {
"pumps":[
{
"id": 1,
"isPrimed":true,
"iName": "Whiskey",
"volume": 850,
"debug": "Test"
},
{
"id": 2,
"isPrimed":true,
"iName": "Vodka",
"volume": 900,
"debug": "Test"
}
]
}
There seem to be several things wrong here. First of all, you're calling JSON.parse on something that's not a string. It's a full-fledged Javascript object. There's no need to parse it; just use it.
Second of all, these two lines have an extra variable each:
data_array.push(data_array, pump_array.pumps[i].volume);
name_array.push(name_array, pump_array.pumps[i].iName);}
Presumably they should read:
data_array.push(pump_array.pumps[i].volume);
name_array.push(pump_array.pumps[i].iName);}
But even if you correct these problems, you still end up with a less-than-ideal data structure:
name_array; //=> ["Whiskey", "Vodka"]
data_array; //=> [850, 900]
Instead of a single, useful data structure, you end up with two different ones that are only useful via shared indices.
How about something like this instead?:
pump_array.pumps.reduce(function(soFar, pump) {
soFar[pump.iName] = pump.volume;
return soFar;
}, {});
//=> {Whiskey: 850, Vodka: 900}
To my eyes, that's a much more useful data structure.

Categories