Storing a Key Value Array into a compact JSON string - json

I want to store an array of key value items, a common way to do this could be something like:
// the JSON data may store several data types, not just key value lists,
// but, must be able to identify some data as a key value list
// --> more "common" way to store a key value array
{
[
{"key": "slide0001.html", "value": "Looking Ahead"},
{"key": "slide0008.html", "value": "Forecast"},
{"key": "slide0021.html", "value": "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
],
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
But, when there is many pairs / items, the string length becomes prohibited,
and I want a compact way, this could be an example:
// --> (1) a "compact" way to store a key value array
{
[
{"slide0001.html", "Looking Ahead"},
{"slide0008.html", "Forecast"},
{"slide0021.html", "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
],
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
Additionally, I want a way to identify the data as a keyvalue array,
because, I may want to store other data in the same JSON file.
I have these examples:
// --> (2) a "compact" way to store a key value array
{
"keyvaluelist":
[
{"slide0001.html", "Looking Ahead"},
{"slide0008.html", "Forecast"},
{"slide0021.html", "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
],
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
// --> (3) a "compact" way to store a key value array
{
"mylist":
{
"type": "keyvaluearray",
"data":
[
{"slide0001.html", "Looking Ahead"},
{"slide0008.html", "Forecast"},
{"slide0021.html", "Summary"},
// another THOUSANDS KEY VALUE PAIRS
// ...
]
},
"otherdata" : { "one": "1", "two": "2", "three": "3" }
}
What do you thing, which one do you suggest, do you have another way ?
Thanks.
UPDATE 1: Remove invalid code. Javascript => JSON
UPDATE 2: Add non key value data
UPDATE 3: Replace "[" and "]" for "{" and "}" in each key value pair

So why don't you simply use a key-value literal?
var params = {
'slide0001.html': 'Looking Ahead',
'slide0002.html': 'Forecase',
...
};
return params['slide0001.html']; // returns: Looking Ahead

If the logic parsing this knows that {"key": "slide0001.html", "value": "Looking Ahead"} is a key/value pair, then you could transform it in an array and hold a few constants specifying which index maps to which key.
For example:
var data = ["slide0001.html", "Looking Ahead"];
var C_KEY = 0;
var C_VALUE = 1;
var value = data[C_VALUE];
So, now, your data can be:
[
["slide0001.html", "Looking Ahead"],
["slide0008.html", "Forecast"],
["slide0021.html", "Summary"]
]
If your parsing logic doesn't know ahead of time about the structure of the data, you can add some metadata to describe it. For example:
{ meta: { keys: [ "key", "value" ] },
data: [
["slide0001.html", "Looking Ahead"],
["slide0008.html", "Forecast"],
["slide0021.html", "Summary"]
]
}
... which would then be handled by the parser.

To me, this is the most "natural" way to structure such data in JSON, provided that all of the keys are strings.
{
"keyvaluelist": {
"slide0001.html": "Looking Ahead",
"slide0008.html": "Forecast",
"slide0021.html": "Summary"
},
"otherdata": {
"one": "1",
"two": "2",
"three": "3"
},
"anotherthing": "thing1",
"onelastthing": "thing2"
}
I read this as
a JSON object with four elements
element 1 is a map of key/value pairs named "keyvaluelist",
element 2 is a map of key/value pairs named "otherdata",
element 3 is a string named "anotherthing",
element 4 is a string named "onelastthing"
The first element or second element could alternatively be described as objects themselves, of course, with three elements each.

For use key/value pair in json use an object and don't use array
Find name/value in array is hard but in object is easy
Ex:
var exObj = {
"mainData": {
"slide0001.html": "Looking Ahead",
"slide0008.html": "Forecast",
"slide0021.html": "Summary",
// another THOUSANDS KEY VALUE PAIRS
// ...
},
"otherdata" : { "one": "1", "two": "2", "three": "3" }
};
var mainData = exObj.mainData;
// for use:
Object.keys(mainData).forEach(function(n,i){
var v = mainData[n];
console.log('name' + i + ': ' + n + ', value' + i + ': ' + v);
});
// and string length is minimum
console.log(JSON.stringify(exObj));
console.log(JSON.stringify(exObj).length);

Related

Is it possible to add a key to a value that does not have a key in JSON?

I have a JSON without a key but just a value. Is it possible to add a key to it using React?
Here I have the and hanging without a key. How do I add a key to it, so that it's easier to read? I looked at JSON.Stringify and checked the replacer but it does not let me do it. delete also does not let me do it.
{
"sample": [
{
"id": "r-1",
"name": "sam"
},
"and",
{
"id": "r-2",
"name": "jerry"
}
]
}
You're confusing objects and arrays. The "key" with the string and as a value isn't a key. It's an array element (the value of the sample property is an array). It can't have a key unless you convert it from a string to an object, like the array elements before and after it, which are objects.
The structure of the array on the sample object property looks like this:
object | string | object
If you're ok changing your data from a string to an object, just replace the second array element (index 1) in the sample property with a new object:
const myObj = {
"sample": [{
"id": "r-1",
"name": "sam"
},
"and",
{
"id": "r-2",
"name": "jerry"
}
]
}
myObj.sample[1] = {
newKey: myObj.sample[1]
};
console.log(myObj);

Manipulating nested array of obects in RedisJSON

I have a JSON with nested array like below to be saved in Redis. I am using RedisJSON module to save the data as JSON.
customer:12345 : {
info : {
key1: val1,
key2: val2,
key3: val3
},
rides: [
{
rideid: xxx,
from: fromval,
to: toval,
date: dateofride,
distance: distanceval,
points: pointsval
},
{
rideid: yyy,
from: fromval,
to: toval,
date: dateofride,
distance: distanceval,
points: pointsval
},
...
]
}
I have a case where a new item can be added to the array or the existing one can be edited. I am using node-redis client with express.js. Express app receives only the data which is changed or added in rides array. If the item is already in the array, new data has to replace the existing array item (rideid is the key of each object), else it has to be added to the array. How do I achieve this?
Given the following JSON document
{
"info": {
"key1": "val1"
},
"rides": [{
"rideid": "xxx",
"points": 0
},
{
"rideid": "yyy",
"points": 10
}
]
}
Which is held by the key customer:12345 in RedisJSON with the following command
127.0.0.1:6379> JSON.SET customer:12345 . "{\"info\": {\"key1\": \"val1\",\"key2\": \"val2\",\"key3\": \"val3\"},\"rides\":[{\"rideid\": \"xxx\",\"points\": 0 },\t{\"rideid\": \"yyy\",\"points\": 10}]}"
You can update ride with rideid yyy by e.g. incrementing the score by 5 as follows
127.0.0.1:6379> JSON.NUMINCRBY customer:12345 "$.rides[?(#.rideid=='yyy')].points" 5
"[15]"
$.rides[?(#.rideid=='yyy')].points is a JSONPath expression (more here and here and also answered here)
To add a new ride
127.0.0.1:6379> JSON.ARRAPPEND customer:12345 $.rides "{\"rideid\": \"zzz\",\"points\": 5 }"
1) (integer) 3
All RedisJSON commands can be found here

how to remove [] character at extracted json using json path

{
"responseCode": "200",
"data": {
"sequence": 1,
"used": true,
"sensingTags": [
{
"code": "LED",
"value": 1,
"updatedOn": 1587557350251
}
]
}
}
My goal is get updatedOn value from this json using jsonPath like this
1587557350251
i thought below jsonPath will work but it extract only empty list.
$..sensingTags[?(#.code == 'LED')][0].updatedOn
And i want to know how to extract value like below
{
"code": "LED",
"value": 1,
"updatedOn": 1587557350251
}
Not like this one.
[
{
"code" : "LED",
"value" : 1,
"updatedOn" : 1587557350251
}
]
As per Getting a single value from a JSON object using JSONPath, JsonPath will always return an array (or a false) at that point...
Best you can do is process it as an array of updatedOn and simply always grab the first value.
$..sensingTags[?(#.code == 'LED')].updatedOn

Jolt reference first element in array as target name

I have been looking at this for a few weeks (in the background) and am stumped on how to convert JSON data approximating a CSV into a tagged set using the NiFi JoltTransformJson processor. What I mean by this is to use the data from the first row of an array in the input as the JSON object name in the output.
As an example I have this input data:
[
[
"Company",
"Retail Cost",
"Percentage"
],
[
"ABC",
"5,368.11",
"17.09%"
],
[
"DEF",
"101.47",
"0.32%"
],
[
"GHI",
"83.79",
"0.27%"
]
]
and what I am trying to get as output is:
[
{
"Company": "ABC",
"Retail Cost": "5,368.11",
"Percentage": "17.09%"
},
{
"Company": "DEF",
"Retail Cost": "101.47",
"Percentage": "0.32%"
},
{
"Company": "GHI",
"Retail Cost": "83.79",
"Percentage": "0.27%"
}
]
I see this as primarily 2 problems: getting access to the content of the first array and then making sure that the output data does not include that first array.
I would love to post a Jolt Specification showing myself getting somewhat close, but the closest gives me the correct shape of output without the correct content. It looks like this:
[
{
"operation": "shift",
"spec": {
"*": {
"*": "[&1].&0"
}
}
}
]
But it results in an output like this:
[ {
"0" : "Company",
"1" : "Retail Cost",
"2" : "Percentage"
}, {
"0" : "ABC",
"1" : "5,368.11",
"2" : "17.09%"
}, {
"0" : "DEF",
"1" : "101.47",
"2" : "0.32%"
}, {
"0" : "GHI",
"1" : "83.79",
"2" : "0.27%"
} ]
Which clearly has the wrong object name and it has 1 too many elements in the output.
Can do it, but wow it is hard to read / looks like terrible regex
Spec
[
{
// this does most of the work, but producs an output
// array with a null in the Zeroth space.
"operation": "shift",
"spec": {
// match the first item in the outer array and do
// nothing with it, because it is just "header" data
// e.g. "Company", "Retail Cost", "Percentage".
// we need to reference it, but not pass it thru
"0": null,
//
// loop over all the rest of the items in the outer array
"*": {
// this is rather confusing
// "*" means match the array indices of the innner array
// and we will write the value at that index "ABC" etc
// to "[&1].#(2,[0].[&])"
// "[&1]" means make the ouput be an array, and at index
// &1, which is the index of the outer array we are
// currently in.
// Then "lookup the key" (Company, Retail Cost) using
// #(2,[0].[&])
// Which is go back up the tree to the root, then
// come back down into the first item of the outer array
// and Index it by the by the array index of the current
// inner array that we are at.
"*": "[&1].#(2,[0].[&])"
}
}
},
{
// We know the first item in the array will be null / junk,
// because the first item in the input array was "header" info.
// So we match the first item, and then accumulate everything
// into a new array
"operation": "shift",
"spec": {
"0": null,
"*": "[]"
}
}
]

Using JPath, how do I return a value based on another key value pair of the same node?

I have the following JSON file. It is truncated for brevity of this question. An actual JSON file would contain 10 - 20 messages and 3 - 15 results.
{
"messages": [
{
"type": "msgInfo",
"description": "Some stuff happened"
},
{
"type": "msgInfo",
"description": "More stuff happened"
},
{
"type": "msgInfo",
"description": "yup, more stuff happened"
}
],
"results": [
{
"parameterId": "val_1",
"dataType": "Double",
"value": 123.45
},
{
"parameterId": "val_2",
"dataType": "Double",
"value": 246.80
},
{
"parameterId": "val_3",
"dataType": "Double",
"value": 135.79
},
{
"parameterId": "val_4",
"dataType": "Long",
"value": 20161021
}
]
}
I'm trying to retrieve the value of the value key based on the value of the parameterId key. For example, I need to return "123.45" using a JPath to "val_1".
So far I have this code (copied from this post) but I can't get the path correct.
JObject obj = JObject.Parse(json);
JToken token = obj["results"]["parameterId"];
Console.WriteLine(token.Path + " -> " + token.ToString());
Console.ReadLine();
What do I need to do in order to return "123.45" using a JPath to "val_1"?
To get the value token from one of the results in the results array based on the value of the parameterId token, you need to use the SelectToken method with a JSONPath query expression:
JToken token = obj.SelectToken("$.results[?(#.parameterId=='val_1')].value");
JSONPath syntax can be a little tricky to get right sometimes, depending on what you're trying to do, so you might find an online expression evaluator such as this one helpful to experiment with.
Alternatively, you can use a LINQ query to do the same thing:
JToken token = obj["results"]
.Where(result => (string)result["parameterId"] == "val_1")
.Select(result => result["value"])
.FirstOrDefault();
Here is a fiddle showing both approaches: https://dotnetfiddle.net/8qiSCa