I'm working on implementing translations in my app, however the format of my translations is not usable for me. I made a shell script that uses jq
to try to modify this array, but I cannot get the output that I desire.
The JSON I get from my service looks something like this.
{
"result": {
"terms": [
{
"term": "title",
"translation": {
"content": "Welcome to {{user}}"
}
},
{
"term": "car",
"translation": {
"content": {
"one": "car",
"other": "cars"
}
}
}
]
}
}
The output that I want is something like this.
{
"title": "Welcome to {{user}}",
"car_one": "car",
"car_other": "cars",
}
I've managed to strip away the uneeded parts of my objects, but I can't figure out how to append something to they key, e.g. turning "car" into "car_one". Or actually just adding the keys properly to the array.
This is currently where I'm at https://jqplay.org/s/P6KIEVX5sWp
CodePudding user response:
The requirements aren't entirely clear to me, but the following does follow the logic of your approach and does produce the required output:
.result
| [.terms[]
| if .translation.content|type == "string" then {title: .translation.content}
else .term as $term
| .translation
| (.content|keys) as $keys
| ([$keys[] as $key | {($term "_" $key): .content[$key]}] | add)
end ]
| add
CodePudding user response:
Probably not the most efficient solution, but this oughta work and is kinda readable:
.result.terms
| map(
(select(.translation.content | type == "object")
| .term as $term | .translation.content | to_entries[] | .key |= "\($term)_\(.)"),
(select(.translation.content | type == "string")
| { key: .term, value: .translation.content })
)
| from_entries
Or with if-then-else:
.result.terms
| map(
if .translation.content | type == "object" then
.term as $term | .translation.content | to_entries[] | .key |= "\($term)_\(.)"
else
{ key: .term, value: .translation.content }
end
)
| from_entries
Cleverly place (and name) the variable and you get down to:
.result.terms
| map(.term as $key
| .translation.content
| if type == "object" then
to_entries[] | .key |= "\($key)_\(.)"
else
{ $key, value: . }
end
)
| from_entries
Even more concise by combining the optional/error suppression operator with the alternative operator:
.result.terms
| map(.term as $key
| .translation.content
| (to_entries[] | .key |= "\($key)_\(.)")? // { $key, value: . }
)
| from_entries
Or, if you prefer (so many possibilities):
.result.terms
| map(
.term as $key
| .translation.content as $value | $value
| (to_entries[] | .key |= "\($key)_\(.)")? // { $key, $value }
)
| from_entries
"\($key)_\(.)"
is string interpolation and equivalent to ($key "_" .)