Replacing JSON file with CSV for d3js - json

http://bl.ocks.org/robschmuecker/7880033
I'm new to javascript and d3. The above example is a dendrogram. I can create my own. However, if I wanted to use it for something like employee data, it seems like it would be a pain to always having to be editing the json unless I'm missing some easier trick.
A csv in excel, that I've used in other charts, would seem like it would work well. Is It possible to replace the flare.json with a csv with the data? if so , how?

No, it's not possible directly. To know why, you'll have to understand the way the function d3.csv creates an array. Suppose you have this CSV:
foo, bar, baz
21, 33, 5
1, 14, 42
When parsed, it will generate a single array of objects, without nested arrays or nested objects. The first row defines the key names, and the other rows the values. This is the array generated for that CSV:
[
{"foo": 21, "bar": 33, "baz": 5},
{"foo": 1, "bar": 14, "baz": 42}
]
Or, if you don't change the type, with the numbers as strings:
[
{"foo": "21", "bar": "33", "baz": "5"},
{"foo": "1", "bar": "14", "baz": "42"}
]
You will not get anywhere close of what you want, which is an array of objects containing arrays containing objects containing arrays etc...
You can modify this array later to create the nested children you need (look at #torresomar comment below), but it's way easier to simply edit your JSON.

Related

How do I access certain elements with jmespath using slicing?

I have the following JSON
{
"items": [
{
"configurationStatus": "SYNCED",
"conflictDetectionState": "IN_SYNC",
"connectivityState": "ONLINE",
I can access individual elements inside with items[*].isModel, but, I cannot figure out how to access the first 3 elements. I tried something like this items[*].[0:2], but it didn't work. I am curious how to access the first 3 elements using slicing.
You would possibly face some issue trying to achieve this because, as pointed in the JMESPath documentation, object are:
object (an unordered collection of key value pairs)
Source: https://jmespath.org/specification.html, emphasis, mine
So you might end up with different keys based on the implementation and have really random results.
Now the issue with your approach is that slices can only act on arrays.
A slice expression allows you to select a contiguous subset of an array.
Source: https://jmespath.org/specification.html#slices, emphasis, mine
What you could do then, in order to have an array out of a hash is to use the values function, but mind that you'll lose the key/value association in the process.
Then, given you have an array, you can now apply the slicing technique.
So with the query:
items[].values(#)[0:3]
On the JSON:
{
"items": [
{
"configurationStatus": "SYNCED",
"conflictDetectionState": "IN_SYNC",
"connectivityState": "ONLINE",
"foo": "bar",
"baz": "qux"
},
{
"configurationStatus": "SYNCED′",
"conflictDetectionState": "IN_SYNC′",
"connectivityState": "ONLINE′",
"foo": "bar′",
"baz": "qux′"
}
]
}
This would give:
[
[
"SYNCED",
"IN_SYNC",
"ONLINE"
],
[
"SYNCED′",
"IN_SYNC′",
"ONLINE′"
]
]

How can I spread an object's properties in jq?

If I need to access the properties of an object, I'm currently accessing each property manually:
echo '{"a": {"a1":1, "a2": 2}, "b": 3}' | jq '{a1:.a.a1, a2: .a.a2,b}'
{
"a1": 1,
"a2": 2,
"b": 3
}
I'd like to avoid specifying every property. Is there an equivalent to the Object spread operator in JS, something like jq '{...a, b}'?
You can add objects together to combine their contents. If a key exists in both the left and right objects the value from the right object will remain.
echo '{"a": {"a1":1, "a2": 2}, "b": 3}' | jq '.a+{b}'
{
"a1": 1,
"a2": 2,
"b": 3
}
If you want a completely generic solution:
[..|objects|with_entries(select(.value|type!="object"))]|add
Or if you want a depth-first approach, replace add by reverse|add.
The above of course comes with the understanding that add resolves conflicts in a lossy way. If you don’t want any lossiness, choose a different method for combining objects, or maybe don’t combine them at all.
Here is a solution that only examines the top-level values, without referring to any key by name:
with_entries(if .value|type=="object" then .value|to_entries[] else . end)
For the example, this produces:
{
"a1": 1,
"a2": 2,
"b": 3
}
Note that even though this solution doesn't use add explicitly, it comes with a similar caveat about key collisions.

Convert JSON array and keys to JSON dict

I've noticed that some APIs use a format of sending a stripped down version of their data via a JSON array like the following:
[
"joe",
[
5,
2,
"yellow"
]
]
And store a set of keys like the following:
[
"name",
["some_data", [
"favorite_number",
"least_favorite_number",
"car_color"
]]
]
To turn the data from a bunch of random values to a readable set of data, like the following:
{
"name": "joe",
"some_data": {
"favorite_number": 5,
"least_favorite_number": 2,
"car_color": "yellow"
}
}
I was wondering how this could be done? I'd prefer it'd be in python, but I'm fine with programming my own libraries.
After grasping at more straws than I could fit in my mouth, I've figured it out. JSON schema is what I'm supposed to be using!

How to take key value pairs and turn them into an array of objects using JMESPath

I'm looking to change the data structure of a 3rd party API using JMESPath and haven't been able to figure out how to take a single object of key-value pairs and restructure this to an array of objects, each containing key-value pairs.
I've gone through all of the JMESPath docs and examples without finding the specific data structure I've been working with. I've tried using the keys(#) and values(#) built-in functions to grab the key and values of these pairs, but haven't been able to join them together into a single array.
Here is my original JSON data
{
"time": 32,
"terms": {
"192.168.10.121": 84,
"154.223.10.121": 12,
"112.149.10.121": 6
}
}
I'm trying to convert the above JSON data to the following strucutre using JMESPath.
{
"data": [
{ "ip_address": "192.168.10.121", "count": 84 },
{ "ip_address": "154.223.10.121", "count": 12 },
{ "ip_address": "112.149.10.121", "count": 6 }
]}
I've been able to create an array of the keys or an array of values, but not able to create the array of objects containing key-value pairs.
terms.{ data: keys(#)}
terms.{ data: values(#)}
Result when using terms.{ data: keys(#)}
{
"data": [
"192.168.10.121",
"154.223.10.121",
"112.149.10.121"
]}
Result when using terms.{ data: values(#)}
{
"data": [
84,
12,
6
]}
Those two functions seem like the only functions I can use to pull the keys and values from an object containing key-value pairs not originally within an array. From what I can tell, I'm not able to combine both of those functions to output a single array like my example above.
I'm not even sure this is possible using JMESPath. Any expert opinion would be greatly appreciated.
Context
jmespath query language
how to re-normalize data from one structure (schema) to another
how to effectively iterate and filter on object properties (name-value pairs)
Pitfalls
Generally speaking, jmespath is highly flexible in iterating sequentially-indexed arrays, but much less flexible in iterating over object properties
Most transformations with jmespath become extremely cumbersome when the goal is to iterate over object properties
Usually you can produce any arbitrary output in jmespath if you are willing to "manually construct" the output by hand ... this is usually the trade-off when dealing with iterating over object properties (aka name-value pairs)
Example
Given the following original dataset ...
{"time": 32,
"terms": {
"192.168.10.121": 84,
"154.223.10.121": 12,
"112.149.10.121": 6
}
}
... the following jmespath query ...
{"data": [
{ "ip_address": #.terms|keys(#)[0], "count": #.terms|values(#)[0] }
,{ "ip_address": #.terms|keys(#)[1], "count": #.terms|values(#)[1] }
,{ "ip_address": #.terms|keys(#)[2], "count": #.terms|values(#)[2] }
]}
... produces the following result
{"data": [
{ "ip_address": "192.168.10.121", "count": 84 },
{ "ip_address": "154.223.10.121", "count": 12 },
{ "ip_address": "112.149.10.121", "count": 6 }
]}

Parse JSON data into Scala List and HashMap

I have JSON data shown below. I am using Python to encode a list, a dictionary and another list into JSON. The final JSON data will look like so:
{
"0": [3, 3, 3],
"1": {
"0": [0, 8, 9],
"1": [1, 2, 3, 4, 10, 11],
"2": [4]
},
"2": [1, 1, 1, 1]
}
My aim is to write some type of Scala function to extract the JSON data in a way that allows:
"0": [3, 3, 3] to be a List(3,3,3)
{"0":[0,8,9], ...} to be a HashMap[Int,List[Int]]
"2": [1, 1, 1, 1] to be a List(1,1,1,1)
Note the length of original Python list and dictionary will vary in size, and the "0", "1", "2" will always be there representing the list, dictionary and list in this order.
I am quite new to Scala and struggling on how to do it without using external libraries. I am trying to use spray-json to do it, since I am using a newer version of Scala (no built-in json parser).
That doesn't look like valid JSON to me, which means any of the JSON parsers you could use won't work. Is that structure fixed? You may want to instead convert it to something thats valid JSON.
eg.
{
"list" : [ 1,1,1],
"someotherObject" : {
"0" : [1,2,3]
},
"anotherList" : [9,8,7]
}
Then you could use Argonaut (for example), and define a decoder, which tells how to map that JSON to object types you specify. See http://argonaut.io/doc/codec/