I'm trying to figure out how to print just the attributes->preferences section in the following JSON example using jq. What's throwing me is that this is an array that contains multiple entries that are identified by an id key value pair and I need the attributes->preferences section just from the array element with id 1 without knowing the exact order of the array entries ahead of time.
[
{
"id": 1,
"attributes": {
"preferences": {
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
...
}
},
...
},
{
"id": 2,
...
},
{
"id": 4,
...
},
...
]
My desired output would be:
{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
...
}
jq '.[] | select( .id == 1 ) | .attributes.preferences'
Demo on jqplay
Related
I'm very new to MongoDB and I need help figuring out how to perform aggregation on a key in MongoDB and use that result to return matches.
For example, if I have a collection called Fruits with the following documents:
{
"id": 1,
"name": "apple",
"type": [
"Granny smith",
"Fuji"
]
}, {
"id": 2,
"name": "grape",
"type": [
"green",
"black"
]
}, {
"id": 3,
"name": "orange",
"type": [
"navel"
]
}
How do I write a query that will return the names of the fruits with 2 types, ie apple and grape?
Thanks!
Demo - https://mongoplayground.net/p/ke3VJIErhvb
use $size to get records with 2 number of type
https://docs.mongodb.com/manual/reference/method/db.collection.find/#mongodb-method-db.collection.find
The $size operator matches any array with the number of elements specified by the argument. For example:
db.collection.find({
type: { "$size": 2 } // match document with type having size 2
},
{ name: 1 } // projection to get name and _id only
)
To get the length of the array you should use $size operator in $project pipeline stage
So the pipeline $project stage should look like this
{
"$project": {
"name": "$name",
type: {
"$size": "$type"
}
}
}
Here is an working example of the same ⇒ https://mongoplayground.net/p/BmS9BGhqsFg
Can anyone help me get the correct jq command to flatten the below example? I've seen a few other posts and I'm hacking away at it but can't seem to get it. I'd greatly appreciate any help.
Input:
[
{
"name": "level1",
"children": [
{
"name": "level2",
"children": [
{
"name": "level3-1",
"children": []
},
{
"name": "level3-2",
"children": []
}
]
}
]
}
]
Output:
[
{
"displayName": "level1",
"parent": ""
},
{
"displayName": "level2",
"parent": "level1"
},
{
"displayName": "level3-1",
"parent": "level2"
},
{
"displayName": "level3-2",
"parent": "level2"
}
]
Here's a straightforward solution that does not involve a helper function and actually solves a more general problem. It is based on the idea of beginning by adding a "parent" key to each child, and then using .. to collect all the name/parent pairs.
So first consider:
[ walk(if type=="object" and has("children")
then .name as $n | .children |= map(.parent = $n)
else . end)
| ..
| select(type=="object" and has("name"))
| {displayName: .name, parent}
]
This meets the requirements except that for the top-level (parentless) object, it produces a .parent value of null. That would generally be more JSON-esque than "", but if the empty string is really required, one has simply to replace the last non-trivial line above by:
| {displayName: .name, parent: (.parent // "")}
With a simple recursive function:
def f: .name as $parent | .children[] | {$parent, displayName: .name}, f;
[ {name: "", children: .} | f ]
Online demo
Given this
var applicationPayload =
[
"main": [
"key1": "value1",
"key2": [
"inside1": "insideValue1"
]
]
]
How can I append or add something inside key2 property.. I'd like the result to be something like this
[
"main": [
"key1": "value1",
"key2": [
"newInside2": "newInsideValue2",
"inside1": "insideValue1"
]
]
]
I tried doing this does not seems to work
applicationPayload["main"]["key2"]["newInside2"] = "newInsideValue2"
You could create a variable containing the current value of key2 and modify that before rewriting it back into the original dictionary:
import Foundation
var applicationPayload =
[
"main": [
"key1": "value1",
"key2": [
"inside1": "insideValue1"
]
]
]
print("Before: \(applicationPayload)")
var key2Value = applicationPayload["main"]?["key2"] as! [String: String]
key2Value["newInside2"] = "newInsideValue2"
applicationPayload["main"]?["key2"] = key2Value
print("After: \(applicationPayload)")
Output:
Before: ["main": ["key1": "value1", "key2": ["inside1": "insideValue1"]]]
After: ["main": ["key1": "value1", "key2": ["inside1": "insideValue1", "newInside2": "newInsideValue2"]]]
You can try for easy access/assign with keyPath
// get value of key2
var res = applicationPayload[keyPath:"main.key2"] as! [String:Any]
// add the other key
res["newInside2"] = "newInsideValue2"
// mutate key2
applicationPayload[keyPath:"main.key2"] = res
For more about keypaths check https://oleb.net/blog/2017/01/dictionary-key-paths/
This is a follow-up on
jq select error: "Cannot index string with string <object>"
Previously, I can filter the entries in a json file that has the target objects with the following command and filter:
[{
"input": {
"obj1": {
"$link": "randomtext1"
},
"id": "a"
}
}]
jq -r '.[] | select( any(.input[]; type=="object" and has("$link") and (.["$link"]=="randomtext1")))|.id'
will give "a"
How can I filter if now the key "$link" and its value "randomtext1" belong to an array?
[{
"input": {
"obj1": [{
"$link": "randomtext1"
}],
"id": "a"
}
}]
(I still want to be able to find "a" as the result)
Example .json:
[
{
"input": {
"obj1": [{
"$link": "randomtext1"
}],
"obj2": [{
"$link": "randomtext2"
}],
"someotherobj": "123"
},
"id": "a"
},
{
"input": {
"obj3": {
"$link": "randomtext1"
},
"obj4": {
"$link": "randomtext2"
}
},
"id": "b"
}
]
I am hoping to find both a and b with "randomtext1" keyword but only got b with the same filter from the previous case after obj1 and obj2 have been "shielded/masked" by the array brackets in the example json file.
Simply add an "or" to cover the new possibility:
.[]
| select( any(.input[];
(type=="object" and (has("$link") and (.["$link"]=="randomtext1")))
or (type=="array" and any(.[];
type == "object" and (has("$link") and (.["$link"]=="randomtext1")))) ))
|.id
... or more readably:
def relevant($txt):
type == "object" and has("$link") and (.["$link"]==$txt);
.[]
| select( any(.input[];
relevant("randomtext1")
or (type=="array" and any(.[]; relevant("randomtext1"))) ))
|.id
Let's say this is how my json looks like and it contains an array:
{
"status": {
"time": 175
},
"hits": [
{
"key1": "value1",
"key2": "value2"
},
{
"key1": "value1",
"key2": "value2"
},
{
"key1": "value1",
"key2": "value2"
},
]
}
I want to create an array of maps like this in react:
[
{mapkey1: value1, mapkey2: value2},
{mapkey1: value1, mapkey2: value2},
{mapkey1: value1, mapkey2: value2},
]
I already have a map of mapkeys to their xpaths in source json:
{
mapkey1: xpath1,
mapkey2: xpath2
}
How can I parse this map into another array using Lodash?
I know how to do it when there is no array:
_.mapValues(
xpathsMap,
paths => _.get(data, paths),
);
var arr = [
{
"key1": "value1",
"key2": "value2"
},
{
"key1": "value1",
"key2": "value2"
},
{
"key1": "value1",
"key2": "value2"
},
];
var output = [];
_.forEach(arr, function(obj) {
var keys = Object.keys(obj);
var ob = {};
_.forEach(keys, function(key) {
ob['map' + key] = obj[key];
})
output.push(ob);
});
console.log(output);
This will give you the desired output -
[
{mapkey1: "value1", mapkey2: "value2"},
{mapkey1: "value1", mapkey2: "value2"},
{mapkey1: "value1", mapkey2: "value2"}
]
Use Array#map to create a new array of objects. Create the object keys you require, using lodash's _.mapKeys():
const data = {"status":{"time":175},"hits":[{"key1":"value1","key2":"value2"},{"key1":"value1","key2":"value2"},{"key1":"value1","key2":"value2"}]}
const result = data.hits.map((o) => _.mapKeys(o, (val, key) => `map${key}`));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>