d3js dynamically accessor children - json

I am creating with the d3 tree layout a tree. My data is as already as a tree but not with the d3js format ( {name: "", "childrend": []} ) but with a simple JSON tree format like :
[{
"A": [{
"AA": []
}, {
"AB": []
}, {
"B": [{
"BA": []
}, {
"BB": []
}]
}]
}]
Of course, the data is not with "A" and "B", is just for making the JSON more clear and give just a part of my data. (My data not following a pattern as the exemple)
I saw i could use tree.children() to change the name, but how can i dynamically do it ?!
I need to use this tree format with d3 tree layout.

So since you can write an accessor function, you can make it smarter than just returning a single property.
The function can be made to check each object key and return it if the corresponding value contains children.

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 to split json using EvaluateJsonPath processor in NiFi

I want to split and transfer the json data in NiFi, Here is my json structure look like this;
I want to split json by id1,id2 array of json transfer to respective processor group say example processor_group a,b. I tried with evaluate json path $.id1,$.id2 but i didn't get exact solution. Can you please help me out from this issue;
{
"id1": [{
"u_name": "aa"
}, {
"addr": "bb"
}],
"id2": [{
"u_name": "aa"
}, {
"addr": "bb"
}]
}
The processor you're looking for is SplitJSON.
Configure it as follows:
Then, you'll receive two FlowFiles:
First one will contain the id1:
[{
"u_name": "aa"
}, {
"addr": "bb"
}]
second one will contain id2:
[{
"u_name": "aa"
}, {
"addr": "bb"
}]
Here is how to get to the values you want with EvaluateJsonPath:
#varun_rathinam Accessing json in an array object via EvaluateJsonPath can be quite confusing.   I also notice the structure of your json is kind of confusing with same values in both.  I have adjusted id2 for cc and dd for testing so that I can tell id1 and id2 values apart.
The solution you want is (see template for exact string values):
Notice we use the normal tree for each json object ( $.object ) then access the array ( 0, 1 ) then access the array's objects.   Also notice it is possible to access the json object array with or without a . before the [.
Reference:
https://community.cloudera.com/t5/Support-Questions/how-to-extract-fields-in-flow-file-which-are-surrounded-by/m-p/208635
You can also find my template during testing of your issue on my GitHub:
https://github.com/steven-dfheinz/NiFi-Templates/blob/master/NiFI_EvaluateJsonPath_Demo.xml

JSONata data mapping template

I'm starting to use JSONata for data transformation and I was wondering if there exists a way to have a file which contains values transformation for some fields in json file.
I will have to do multiple transformation types, but most cases will be to translate a field value from "A" to "B" for example and I will be easier to do that in a file in order to not create new versions of data transformation and just will be necessary to create a new entry in this file.
Regards
You can use $lookup to perform simple mappings. For example, with the following JSON:
{
"mapping": [
{ "a": "a1" },
{ "b": "b1" }
],
"values": [
"a", "b"
]
}
You can map the values using:
values.$lookup($$.mapping, $)
In which case the result will be:
[
"a1",
"b1"
]
Alternatively you can look at $sift which will allow you to write a function to sift through the mappings.

Having a problem with iterating over multiple json objects and showing them in div with vue.js

Trying to create a website that takes in information from an API, however I don't really understand how to do it seeing that I need all results grouped up and the API I've created almost never gives a response with the same amounts of objects. So the question is, seeing that I use vue.js and axios is there any way to loop through the json objects to show each of the objects in a seperate ? I manage to do it when there are a specified amounts, but I want to make it dynamic so I don't hardcode into the variables what part of the response I need to set to each variable.
UPDATE: I've tried to use v-for, but seeing that I need to have the output quite structured it doesn't really help, I've also tried Nested V-for loops, once again I can't get the accuracy that I'm looking for.
UPDATE2: Also should be added, when I say JSON object I actually ment js object. the json.parse() has been used on the json.
UPDATE3: Updated the JSON to actual data that I'm using for the application.
Every div need a lemma, a paradigm tagset, inflection tagset and inflectionForms and a table for all the meanings. Just need meaning not meaningText. TranslationId is not important. The JTranslate that wraps every object will be removed, just kinda tired of the Java at the moment, will do that later today and do the adjustments on the vue projects aswell regarding that deletion.
Actually your json format is invalid
{
"object1":{
"name": "test",
"data": "test"
},
"object2":{
"name": "test2",
"data": "test2"
},
"object3":{
"name": "test2",
"data": "test2"
}
}
it should be like above and use JSON.parse() method to simply convert the json to javascript object
Valid Object:
var objects = {
"object1":{
"name": "test",
"data": "test"
},
"object2":{
"name": "test2",
"data": "test2"
},
"object3":{
"name": "test2",
"data": "test2"
}
}
for iteration use
<div v-for="(object,index) in objects" :key="index">
{{object}}
</div>
The correct object as an array:
test: [
{
object1: {
name: 'name1',
data: 'content1'
}
},
{
object2: {
name: 'name1',
data: 'content1'
}
},
{
object3: {
name: 'name3',
data: 'content3'
}
}
]
can be mapped as a computed property inside the script tages:
computed: {
mappedTest() {
return this.test.map(entry => {
const key = Object.keys(entry)[0];
return { name: entry[key].name, data: entry[key].data };
});
}
},
and call it inside the template
<div
v-for="testObject in mappedTest"
:key="testObject"
>
name: {{testObject.name}}; data: {{testObject.data}}
</div>
I was very tired when I asked this question, apparently I did everything wrong. Can easily be solved by nested v-for loops.

typeahead nested json object

I am new to Ember and JSON. I want to parse a JSON object that is below with typeahead library
and access nested object values by searching their keys.
I have this Json format:
return [
{
"id": 1,
"category_name": "Supermarket",
"category_description": "SUPER MARKET",
"image_url": "",
"merchants": [
{
"name": "CARREFOUR",
"id": 12,
"merchant_type_id": 1,
"merchant_type_description": "Gold",
"merchant_redeption_rate": 0.002500,
"image_url": "https://jpg",
"branches": [
{
"id": 123456,
"latitude": 37.939483,
"area": "ΑΓ. ΔΗΜΗΤΡΙΟΣ",
"zip": "12345"
},
{
"id": 4567890,
"longitude": 23.650622,
"area": "ΑΓ. ΙΩΑΝΝΗΣ ΡΕΝΤΗΣ",
"zip": "12345"
}
]
},
{
"name": "CAFCO",
"id": 13,
"merchant_type_id": 3,
"merchant_type_description": "None",
"merchant_redeption_rate": 0.002500,
"image_url": "https:.jpg",
"branches": [
{
"id": 127890,
"latitude": 38.027870,
"area": "ΠΕΡΙΣΤΕΡΙ",
"zip": "12345"
}
]
}
]
},
{
"id": 2,
"category_name": "Πολυκαταστήματα",
"category_description": "ΠΟΛΥΚΑΤΑΣΤΗΜΑ",
"image_url": "",
"merchants": [
{
"name": "AGGELOPOYLOS CHR.",
"id": 15,
"merchant_type_id": 2,
"merchant_type_description": "Silver",
"merchant_redeption_rate": 0.002500,
"image_url": "https://www.nbg.gr/greek/retail/cards/reward-programmes/gonational/PublishingImages/aggelopoulos.jpg",
"branches": [
{
"id": 234780,
"latitude": 35.366118,
"longitude": 24.479461,
"address": "ΕΘΝ. ΜΑΚΑΡΙΟΥ 9 & ΕΛ. ΒΕΝΙΖΕΛΟΥ 1",
"area": "Ν. ΦΑΛΗΡΟ",
"zip": "12345"
}
]
}
]
}
];
--------------------------Updated----------------------------
For example, i want to search using typeahead the name of merchants and when the letter we write to search matches the name of merchants it will appear the corresponding category_name and backwards.
Example -> when i keyboard the s it will appear :
Category : Supermarket,
Name: CARREFOUR
Name: CAFCO
And the same output on the dropdown of search when i keyboard the letter c.
Any help?
New Jsbin example
The simplest way (in my mind) to get this to work is to create a computed property that will contain an array of latitudes. But how do we get there?
To get to latitude, you need to go through array of merchants and then array of branches. Being that this will be across multiple elements, you are going to end up with "array of arrays" type data structure, which is annoying to deal with. So, to simplify this, we can create a simple flatten function as follows:
flatten: function(origArray){
var newArr = [];
origArray.forEach(function(el) {
el.forEach(function(eachEl){
newArr.push(eachEl);
});
});
return newArr;
},
In addition to our function above, Ember already provides us with many other useful functions that can be used on arrays (see here). One of those is mapBy(property) which transforms an array into another array only keeping the values of the property we specified.
So, to create a lats (for latitudes) property, we can just do this:
lats: function(){
var merchantsArr = this.get('model').mapBy('merchants');
merchantsArr = this.flatten(merchantsArr);
var branchesArr = merchantsArr.mapBy('branches');
branchesArr = this.flatten(branchesArr);
return branchesArr.mapBy("latitude").compact();
}.property('model')
Above, I am basically using mapBy, flatten (see above) and compact which
Returns a copy of the array with all null and undefined elements removed.
Once you have the lats property with all the necessary data, the rest is easy.
Your call to component becomes:
{{x-typeahead data=lats name='category_name' selection=myColor}}
Note lats instead of model you originally were passing into the component.
And now, to access the value of data property in the component, you do
`this.get('data')`
which you can just pass in as the source like so:
source: substringMatcher(self.get('data'))
Working solution here
Update
Updating my answer based on your updated question.
OK, so this is getting a little more complicated. You now need more than just one property (latitude) from the object. You need category_name and merchant name.
In addition to mapBy, which just grabs one property out of array, Ember also has map which lets you transform the array into pretty much anything you want to:
lats: function(){
var merchantsArr = this.get('model').map(function(thing){
var category_name = thing.category_name;
return thing.merchants.map(function(merchant){
return {
"name": merchant.name,
"category": category_name
};
});
});
merchantsArr = this.flatten(merchantsArr);
return merchantsArr;
}.property('model')
The code above looks complicated, but it's basically just returning an array of top level objects' merchants accompanied by category_name. Since this is an array of arrays, we will need to flatten it.
Then, inside the component, we need to keep in mind that we are not just passing in an array of strings, but rather we are passing in an array of objects. Therefore, we need to look through object's properties (name and category) for a match
$.each(strs, function(i, str) {
if (substrRegex.test(str.name) || substrRegex.test(str.category)) {
matches.push(str);
}
});
Lastly, to actually display both category and merchant name, you need to tell Typeahead how to do that:
templates: {
suggestion: Handlebars.compile('<p>{{name}} – {{category}}</p>')
}
Working solution here