I just started using JSONata and I found it quite fascinating to parse JSON easily. But I have this problem, and I'm not sure if it can be done with JSONata directly.
I want to include a counter that goes from 1 to "the number of objects in an array", like so:
Original output from JSONata expression:
[
{
"a": false,
"b": "",
"c": "",
"d": true
},
{
"a": false,
"b": "",
"c": "",
"d": true
},
{
"a": false,
"b": "",
"c": "",
"d": true
}
]
Wanted output:
[
{
"count": "1",
"a": false,
"b": "",
"c": "",
"d": true
},
{
"count": "2",
"a": false,
"b": "",
"c": "",
"d": true
},
{
"count": "3",
"a": false,
"b": "",
"c": "",
"d": true
}
]
Is it possible? Thank you in advance.
You can use the $map() function to iterate over a list and apply an expression to each item. The second argument of your function will be the index within the array. So for your example, the following will merge the count property into your original array of objects:
$ ~> $map(function($v, $i) {
$merge([{'count': $i+1}, $v])
})
See this working in the JSONata Exerciser: http://try.jsonata.org/rkDpyXMVM
Related
In this json object, I want to add and change the values of the list called "m" while traversing the array called "j". What should I do ??
{
"a": "string",
"h": false,
"i": "string",
"j": [
{
"k": 0,
"l": "NONE",
"m": [
{
"n": "string",
"o": []
}
],
"p": [],
"q": [],
}
],
"r": [
{
"s": "string",
"t": "strin",
"u": "string",
"v": null,
}
]
}
In JavaScript, you'd do something like this:
let obj = JSON.parse(json_data);
for(let key in obj.j){
if(key=='m'){
//if you want to skip 'm'
continue;
}
let value = obj.j[key];
//do stuff
}
This is the way to traverse and modify the array and its elements.
let response={
"a": "string",
"h": false,
"i": "string",
"j": [
{
"k": 0,
"l": "NONE",
"m": [
{
"n": "string",
"o": []
}
],
"p": [],
"q": [],
}
],
"r": [
{
"s": "string",
"t": "strin",
"u": "string",
"v": null,
}
]
}
let newObject=response.j.map(ele=>
{ele.m.map(el=>{el.n="IamChanged",el.myName="IamChanged"})}
)
console.log(response);
What do you want in output??
I have the following:
declare #X nvarchar(max)
set #X='[
{
"a": "",
"b": "",
"c": "",
"e": "",
"f": "",
"g": ""
}
]'
declare #y nvarchar(max)
set #y='{"bac": ""}'
And this is what I need:
'"pro": [
{
"a": "",
"b": "",
"c": "",
"address": {
"bac": ""
},
"e": "",
"f": "",
"g": ""
}
]'
How can I select certain values and/or values conditional on other columns in vega-lite? For example, below I only want to show values that have "red" in the column "c".
{
"data": {
"values": [
{"a": "A", "b": 2, "c": "red"},
{"a": "A", "b": 7, "c": "red"},
{"a": "A", "b": 4, "c": "blue"},
{"a": "B", "b": 1, "c": "blue"},
{"a": "B", "b": 2, "c": "red"}
]
},
"mark": "bar",
"encoding": {
"x": {"field": "a", "type": "nominal"},
"y": {"aggregate": "average", "field": "b", "type": "quantitative"}
}
}
I have tried adding the following code before "mark": "bar", according to this vega github tutorial, and using the online vega editor, but it doesn't filter column b. I thought I could use it to somehow filter a string as well.
"transform": {
"filter": "datum.b > 3"
},
Follow-up question regarding multiple filtering criteria.
You can do this with a filter transform:
{
"data": {
"values": [
{"a": "A", "b": 2, "c": "red"},
{"a": "A", "b": 7, "c": "red"},
{"a": "A", "b": 4, "c": "blue"},
{"a": "B", "b": 1, "c": "blue"},
{"a": "B", "b": 2, "c": "red"}
]
},
"transform": [{"filter": "datum.c == 'red'"}],
"mark": "bar",
"encoding": {
"x": {"field": "a", "type": "nominal"},
"y": {"aggregate": "average", "field": "b", "type": "quantitative"}
}
}
Explanation:
I am using the,
"A":{ "$arrayElemAt" :[ {"$split" : ["$info_id" , "_"]},0]},
"B":{ "$arrayElemAt" :[ {"$split" : ["$info_id" , "_"]},1]},
"C":{ "$arrayElemAt" :[ {"$split" : ["$info_id" , "_"]},2]},
but if after 2nd _ nothing is there then I want the output to be as "NA".
Document 1:
"info": {
"id": "2_452_1",
},
Document 2:
"info": {
"id": "9_5",
},
Expected output Document 1:
{
"A": "2",
"B": "452",
"C": "1"
}
Expected output Document 2:
{
"A": "9",
"B": "5",
"C": "NA"
}
$split to split id string by "_"
$arrayElemAt to get specific element from above result array from split
$ifNull to check return result from the above operation is null then return "NA"
db.collection.aggregate([
{ $project: { info: { $split: ["$info.id", "_"] } } },
{
$project: {
A: {
$ifNull: [{ $arrayElemAt: ["$info", 0] }, "NA"]
},
B: {
$ifNull: [{ $arrayElemAt: ["$info", 1] }, "NA"]
},
C: {
$ifNull: [{ $arrayElemAt: ["$info", 2] }, "NA"]
}
}
}
])
Playground
I have an odd requirement to prettify a JSON structure in a very precise way. Currently I'm using angular.toJson(jsonObj, true) to auto-prettify it.
However, how could I do customized formatting. Given the following JSON:
{"SomeArray": [
{
"Description": "Some sort of description",
"a": 0,
"b": "foo0",
"c": "bar0"
},
{
"a": 0,
"b": "foo1",
"c": "bar1",
"d": "DoSomething1"
},
{
"a": 0,
"b": "foo2",
"c": "bar2",
"d": "DoSomething2"
},
{
"Description": "Another description",
"a": 0,
"b": "foo3",
"c": "bar3",
"d": "DoSomething3"
},
{
"a": 0,
"b": "foo4",
"c": "bar4",
"d": "DoSomething4"
}]}
How can I format this to look exactly like the following? Basically I need to keep "description" keys on it's own seperate line, while the other keys are on a line immediately below it, as well as keeping the curly brace on the same line as well:
{"SomeArray": [
{ "Description": "Some sort of description",
"a": 0, "b": "foo0", "c": "bar0" },
{ "a": 0, "b": "foo1", "c": "bar1", "d": "DoSomething1" },
{ "a": 0, "b": "foo2", "c": "bar2", "d": "DoSomething2" },
{ "Description": "Another description",
"a": 0, "b": "foo3", "c": "bar3", "d": "DoSomething3" },
{ "a": 0, "b": "foo4", "c": "bar4", "d": "DoSomething4" }]}
Figured I'd circle back around and answer how I wound up solving this. Just wound up using HandleBars.js. It's a pretty slick templating engine. I wrote the template of how I want json output to look, then just passed it the object I wanted formatted. The net results was formatting exactly as I needed it, with very little effort!
If anyone else is struggling with formatting JSOn for whatever reason, I strongly recommend checking out Handlebars.