Reputation: 52
I have a JSON input that is nearly-but-not-quite correct geojson, and I'm attempting to use jq to transform it into a correct format. My input is using a custom geometry type of "Path" on some items, and inside the coordinates of these items it's storing some extra data (line curve data for rendering to SVG). I don't want to drop this data, so my goal has been to change all geometry items of type "Path" into a "LineString", and strip out the extra coordinates in these items into a "properties" object (on the geometry item) to preserve the data.
Here's a small example of the input:
{
"type": "FeatureCollection",
"features": [
{
"id": 16683828,
"properties": {
"facility": "hallway"
},
"type": "Feature",
"geometry": {
"type": "Path",
"coordinates": [
[
0,
379.64,
289.412
],
[
3,
379.629,
289.768,
379.346,
290.059,
378.986,
290.066
],
[
1,
373.156,
290.066
],
[
1,
373.156,
298.5
],
[
1,
373.156,
299.469
],
[
4
]
]
}
}
]
}
Here's roughly what I'd like to transform this into:
{
"type": "FeatureCollection",
"features": [
{
"properties": {
"facility": "hallway",
"id": 16683828
},
"type": "Feature",
"geometry": {
"type": "LineString",
"properties": {
"curves": [
{
"coordinate_position": 1,
"control_points": [379.629, 289.768, 379.346, 290.059]
}
]
},
"coordinates": [
[
379.64,
289.412
],
[
378.986,
290.066
],
[
373.156,
290.066
],
[
373.156,
298.5
],
[
373.156,
299.469
]
]
}
}
]
}
The part that's tripping me up is using conditionals inside of a larger jq formatting expression. For each feature, I'm trying to check if geometry.type == "Path", and if so, strip the first item from each coordinate (I don't need it), and then move all but the last two items from the coordinate into a object in a properties.curves array, noting the position within the "coordinates" array, and the extra data. If the geometry.type != "Path", I just want to copy the geometry item to my output.
Here's the script I have so far, including the incorrect conditional logic beginning at geometry: {
:
cat input.json | jq '. |
{
type: .type,
features: [
.features[] | {
type: .type,
properties: {
display_name: .properties.display_name,
id: .id
}
geometry: {
if .geometry.type == "Path" then
type: "LineString"
else
type: .geometry.type
end
}
}
]
}'
Of course what's not working here is the conditional directly inside an object. My best guess is that I need to use more jq pipes but I just haven't been able to figure out how to wrangle it into the correct format.
Upvotes: 0
Views: 94
Reputation: 117027
Many would suggest writing "jq ... FILE" instead of 'cat FILE | jq ...'
You don't need the initial '. |'
Here is a variant of your jq filter that produces the results shown below:
{
type: .type,
features: [
.features[] | {
type: .type,
properties: {
display_name: .properties.facility,
id: .id
},
geometry: {
type: (if .geometry.type == "Path" then "LineString"
else .geometry.type
end)
}
}
]
}
Output:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"display_name": "hallway",
"id": 16683828
},
"geometry": {
"type": "LineString"
}
}
]
}
Upvotes: 1