Loading JSON with D3 when columns are defined separately - javascript

I'm using d3.js and I'm having hard time understanding how can I load a JSON which represents a table (columns and rows), which the columns are defined separately.
A normal JSON, which I have no problem loading may look like this:
[
{
"id": 1,
"name": "A green door",
"price": 12.50
},
{
"id": 2,
"name": "A red door",
"price": 12.50
},
{
"id": 3,
"name": "A blue door",
"price": 12.50
}
]
The corresponding JSON with separated columns will look like this:
{
"columns": [
{
"ColumnName":"id",
"DataType":"number"
},
{
"ColumnName":"name",
"DataType":"string"
},
{
"ColumnName":"price",
"DataType":"number"
}
],
"rows": [
[
"1",
"A green door",
"12.50"
],
[
"2",
"A red door",
"12.50"
],
[
"3",
"A blue door",
"12.50"
]
]
}
Is it possible to make d3.js load this kind of JSON without reconstructing a new JSON?
The original structure of the JSON that I receive is not changeable.
Thank you for helping.

There won't be any problem in loading the JSON with separated columns(Format 2) with d3. You will just need to convert the JSON format after loading it, to match the required format of your d3 layout. For that, you may try the code as shown below.
d3.json("path/to/column_json_file_name.json", function(error, data) {
if (error) return console.warn(error);
var columns = data.columns.map(function(d){ return d.ColumnName });
var jsonInRquiredFormat = data.rows.map(function(row,i){
var ob = {};
ob[columns[0]] = parseInt(row[0]);
ob[columns[1]] = row[1];
ob[columns[2]] = parseFloat(row[2]);
return ob;
});
console.log(jsonInRquiredFormat);
});
Output obtained for sample input:
[{
"id": 1,
"name": "A green door",
"price": 12.5
}, {
"id": 2,
"name": "A red door",
"price": 12.5
}, {
"id": 3,
"name": "A blue door",
"price": 12.5
}]

Related

How to add or update items in this multidimensional JSON?

Let's say we have some houses represented as JSON. Something like this:
[
{
"id": "1",
"code": "1",
"name": "Smith's",
"children": [
{
"id": "",
"code": "11",
"name": "Kitchen",
"children": [
{
"id": "",
"code": "111",
"name": "Sink",
"children": []
}
]
},
{
"id": "",
"code": "12",
"name": "Living Room",
"children": [
{
"id": "",
"code": "121",
"name": "Television",
"children": [
{
"id": "",
"code": "1211",
"name": "Panel buttons",
"children": [
{
"id": "",
"code": "12111",
"name": "Power button",
"children": []
},
{
"id": "",
"code": "12112",
"name": "Colors adjust button",
"children": []
}
]
},
{
"id": "",
"code": "1221",
"name": "Screen",
"children": []
}
]
}
]
}
]
},
{
"id": "2",
"code": "2",
"name": "Taylor's",
"children": [
// Here goes all house places and items like the example above
]
},
{
"id": "1",
"code": "1",
"name": "Wilson's",
"children": [
// Here goes all house places and items like the example above
]
}
]
Take notice that the "code" property, found in each item, is something to represent the "path" until that item, carrying its parents "code" property concatenated with its own position by incremental order. So the code "11" means house 1 and child 1. And 212 would be house 2, child 1, child 2. Also take notice that all items follow the same type. In other words, every item has a children that follows its own type. So, it could be infinite.
Now, I'd like to maintain these structure. Adding items, updating items and so on. Let's say we want to add a carpet in Smith's living room. We would go deep in the structure 2 levels, which are Smith's house (index 0 of the array) and living room (index 1 of the children array). And then add a carpet.
The problem is it won't be 2 levels in all cases. What if I wanted to add a bathroom? It would be level 1, alongside with kitchen in living room (the first children). What if I'd like to add a microwave in the kitchen and add to it buttons, display, etc?
I think I'm a recursive scenario where I have to visit all items and, if it is the one I'm looking to reach at, add/updated it.
I've tried following this example
I couldn't figure it out how to bring it to my case. though.
I appreciate if your contribution is in JavaScript, but feel free to represent it in other language in case you are better in other language =).
There are indeed some questions, like for instance what happens if you have more than 10 items as child and why do you need it?
And what happens if you remove any item on any level? will you recursively start updating all codes?
Nevertheless I gave it a go. In essence what I do in the code is first search for the parent (example: Kitchen) where you want to add it to and then add the new child item (example: Carpet) to it.
The search is a typical recursive search.
The child addition is a typical addition to an array.
For argument's sake I assumed that the fields code always exist and that children is always an array.
// Actual code is underneath the declaration of this array
let houseList = [
{
"id": "1",
"code": "1",
"name": "Smith's",
"children": [
{
"id": "",
"code": "11",
"name": "Kitchen",
"children": [
{
"id": "",
"code": "111",
"name": "Sink",
"children": []
}
]
},
{
"id": "",
"code": "12",
"name": "Living Room",
"children": [
{
"id": "",
"code": "121",
"name": "Television",
"children": [
{
"id": "",
"code": "1211",
"name": "Panel buttons",
"children": [
{
"id": "",
"code": "12111",
"name": "Power button",
"children": []
},
{
"id": "",
"code": "12112",
"name": "Colors adjust button",
"children": []
}
]
},
{
"id": "",
"code": "1221",
"name": "Screen",
"children": []
}
]
}
]
}
]
},
{
"id": "2",
"code": "2",
"name": "Taylor's",
"children": [
// Here goes all house places and items like the example above
]
},
{
"id": "1",
"code": "1",
"name": "Wilson's",
"children": [
// Here goes all house places and items like the example above
]
}
]
addChild(houseList,"11",{name:"Carpet" });
addChild(houseList,"1211",{name: "Volume Up Button"});
addChild(houseList,"1211",{name: "Volume Down Button"});
console.log('new houselist', houseList);
// child is just what you want to add and the parentCode refers to where you want to add it to
function addChild(houseList, parentCode, child) {
let parent = findInHouseList(houseList,parentCode,child);
let amountOfChildren = parent.children.length;
let newCodeName = parentCode +""+ (amountOfChildren+1);
child = {...{id: "", code: newCodeName, children: []}, ...child};
console.log('adding child ', child);
parent.children = [...parent.children, child];
}
function findInHouseList(houseList,code) {
for (let house of houseList) {
let foundElement = findElement(house,code);
if ( foundElement)
return foundElement;
}
}
function findElement(currentElement, code) {
if ( currentElement.code === code)
return currentElement;
if (currentElement.children?.length > 0)
{
for (let child of currentElement.children) {
let foundElement = findElement(child,code);
if ( foundElement)
return foundElement;
}
}
return null;
}
I decided to let the code manage the code names for new children. It seems the easiest.
What you're trying to do is updating a JSON value at a dynamic path.
This function will append a child to the item which holds the specified code.
You may add conditions to check if the item at the code is defined
function appendChild(houses, code, item) {
let path = code.split('')
let o = houses
for (let i = 0; i < path.length; i++) {
let n = path[i] - 1
o = o[n]["children"]
}
o.push(item)
return houses
}
However, you should start your code indexes at 0 and storing them inside the JSON is useless since they are simply the path to reach the item.

JSON named objects vs array with name property

This may be a JS question, I'm not sure.
I am using JSON to store data about enemies in a game. I am currently structuring like this:
{
"Area 1": {
"Enemy Name": {
"type": "Human",
"lvl": 30
},
"Enemy 2": {
"type": "Human",
"lvl": 30
}
},
"Area 2": {
"Enemy 1": {
"type": "Human",
"lvl": 30
},
"Enemy 2": {
"type": "Human",
"lvl": 30
}
}
}
I was wondering if I should be instead using an array of enemies for each area with a "name" property instead. Like this:
{
"Area 1": [
{
"name": "Enemy Name",
"type": "Human",
"lvl": 10
},
{
"name": "Enemy 2",
"type": "Human",
"lvl": 30
}
],
"Area 2": [
{
"name": "Enemy 1",
"type": "Human",
"lvl": 30
},
{
"name": "Enemy 2",
"type": "Human",
"lvl": 30
}
]
}
I believe the second is the way I should be doing it but wanted other's feedback. I think with the first way, I'll need to know the names of the enemies in order to read their data whereas, with the array, I can loop through the areas and read the enemies in each area.
Thanks in advance for any help!
The second option feels right. It is properly structured and you can easily loop through any Area to perform operations on Enemies. My suggestion is to go with second one.
var Map = [
Area1: [
{
name: "Enemy 1";
metaData: '...'
},
{
name: "Enemy 2";
metaData: '...'
}
],
Area2: [
{
name: "Enemy 1";
metaData: '...'
}
]
];
Scanning enemies in particular area.
Map[Area1].forEach(function(enemy) {
//Operation ...
});
I hope this helps. :)

Sorting an array of JavaScript objects by sub array property/value

I have the following data being returned from a server (the structure of this data is something that I do not have control over)...
var data = {
"TrackingResults": [
{
"Name": "Pack One",
"Products": {
"Product": [
{
"ProductName": "Soccer Ball"
},
{
"ProductName": "Tennis Racket"
},
{
"ProductName": "Gold Putter"
}
]
},
"status": "Despatched",
"Location": "Alabama",
"Type": "Parcel"
},
{
"Name": "Pack Two",
"Products": {
"Product": [
{
"ProductName": "Backet Ball Hoop"
},
{
"ProductName": "Base Ball Glove"
}
]
},
"status": "Despatched",
"Location": "Florida",
"Type": "Parcel"
}
]
};
I would like to be able to sort each Tracking Result by the first Product Name. I can't find any code that will sort by a sub array property/value.
You should use the Array.sort method with a custom comparator function:
var resultsComparator = function (res1, res2) {
var prod1 = res1.Products.Product[0].ProductName;
var prod2 = res2.Products.Product[0].ProductName;
return prod1.localeCompare(prod2);
}
This way the ordering is based on the current locale of the web browser. You just pass the function to the sort method:
data.TrackingResults.sort(resultsComparator);
You need to write it manually like: (with the hint on localeCompare from meskobalazs's comment)
var result = data.TrackingResults.sort(function(a,b){
return a.Products.Product[0].ProductName.localeCompare(b.Products.Product[0].ProductName)
});
This should work for sorting TrackingResults

Convert a model in given json format

I have a model in which values are stored in following format:--
Language-count=3
[0]
-ID="1"
-Name="French"
[1]
-ID="2"
-Name="English"
[2]
-ID="3"
-Name="Hindi"
Titles-count=2
[0]
-ID="1"
-Name="Video1"
[1]
-ID="2"
-Name="Video2"
Countries-count=2
[0]
-ID="1"
-Name="India"
[1]
-ID="2"
-Name="USA"
and I have to convert this model in given json format:-
var models = [
{
name: 'Language',
values: [
'English',
'French',
'Hindi'
]
},
{
name: 'Title',
values: [
'Title 1',
'Title 2'
]
},
{
name: 'Countries',
values: [
'India',
'UK'
]
}
];
In above json format I have hard coded those values of Languages,countries and Titles but I have to fetch it from the above model which I have already given.
The json Format which I am getting is following:--
{
"ID": 1,
"DealID": 1,
"Title": "Position1",
"Titles": [
{
"Icon": "hdtv",
"Name": "\nWedding Bells & Farewells\n",
"ID": 12
},
{
"Icon": "hdtv",
"Name": "Delta Farce",
"ID": 5
},
{
"Icon": "hdtv",
"Name": "Doe B: Let Me Find",
"ID": 9
}
],
"Episodes": [
{
"Icon": "episode",
"Name": "Sparkle",
"ID": 4
},
{
"Icon": "episode",
"Name": "Sparks Fly Out",
"ID": 2
},
{
"Icon": "episode",
"Name": "Uploads by Filmi Gaane",
"ID": 7
}
],
"Assets": [
{
"Icon": "file-o",
"Name": "Best of Javed Akhtar - Jukebox 2 - Javed Akhtar Top 10 Hit Songs",
"ID": 10
},
{
"Icon": "file-o",
"Name": "Ep 105 - Sin Say Shun Awards After Party additional image 1",
"ID": 4
},
{
"Icon": "file-o",
"Name": "Ep 105 - Sin Say Shun Awards After Party box cover",
"ID": 3
}
],
"Documents": [],
"Languages": [
{
"Icon": "globe",
"Name": "Albanian",
"ID": 70
},
{
"Icon": "globe",
"Name": "Amharic",
"ID": 96
}
],
"Territories": [],
"Countries": [
{
"Icon": "globe",
"Name": "Afghanistan",
"ID": 2
},
{
"Icon": "globe",
"Name": "Albania",
"ID": 3
},
{
"Icon": "globe",
"Name": "Algeria",
"ID": 4
}
],
"Rights": [
{
"Icon": "leaf",
"Name": "Ancillary",
"ID": 23
},
{
"Icon": "leaf",
"Name": "Finshed Episode Rights",
"ID": 20
},
{
"Icon": "leaf",
"Name": "Format Group - DO NOT USE",
"ID": 63
}
],
"Contributors": [],
"Transmissions": [],
"Available": null
}
It would be best to write a simple parser and transform your data type to JSON - which would additionally allow you to reuse the parser in the future, and convert it to other data types easily for instance.
You could look at the various YAML parsers for inspiration, which would use a similiar technique for your data set's language.
Alternatively you can create a 'hack' and just keep splitting things up if your data format is always of this format, and doesn't allow arbitrary value nesting.
List personel = new List();
var client = new RestClient("your adres");
var request = new RestRequest(Method.GET);
request.AddHeader("Postman-Token", "2893de4a-457e-46a7e8efb025");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("token", "a23a80f7-3323-4594056");
IRestResponse response = client.Execute(request);
JObject deger = JObject.Parse(response.Content);
var toplam = deger["data"]["data"].Count();
string jenp = toplam.ToString();
for (int i = 0; i < toplam; i++)
{
Personeller data = new Personeller();
data.Adi = deger["data"]["data"][i]["adi"].ToString();
data.Soyadi = deger["data"]["data"][i]["soyadi"].ToString();
data.tckimlikno = (long)deger["data"]["data"][i]["tckimlikno"];
personel.Add(data);
}

What is wrong with this JSON file?

I put it in a parser and all it gives me is "expecting string on line 19". I have no idea what that means.
{
"name": "Rajeev",
"children": [
{
"name": "Joe",
"children": [
{
"name": "Kevin",
"children": [
{
"name": "George"
}
]
},
{
"name": "John",
"children": [
{
"name": "Barb",
}{
"name": "Michael",
}{
"name": "Charles"
}
]{
"name": "Ravinder"
]
},
Your commas are in the wrong place, e.g.
"children": [
{
"name": "Barb"
},{
"name": "Michael"
},{
"name": "Charles"
}
]
The left one is the right one. see for yourself. you had many extra , and unclosed { and [
http://i.stack.imgur.com/9yKNN.jpg
You have a property / value:
"name": "Barb",
… with a trailing comma so the next thing must be another property / value (the string mentioned in the error message is the property name).
However you have:
}{
Either remove the comma or add more details about Barb.
Then you will need to put a comma between the two objects:
}, {
It seems likely that you intended to place the comma causing teh error between the two objects, so you can just move them.
(You have similar errors throughout the rest of the file)
Sorry for the first answer, I saw a missing comma and automatically assumed that was it, but there were many other errors in there. I think this is what you're trying to do
[
{
"name": "Rajeev",
"children": [
{
"name": "Joe",
"children": [
{
"name": "Kevin",
"children": [
{
"name": "George"
}
]
},
{
"name": "John",
"children": [
{
"name": "Barb"
},
{
"name": "Michael"
},
{
"name": "Charles"
}
]
}
]
}
]
},
{
"name": "Ravinder"
}
]

Categories