I need to restructure some JSON files to clean up the data representation. Part of this restructuring includes grouping similar objects in a parent object rather than relying on a particular property of the object. We will have five "sections" in the files:
attributes
, associatedObjects
, inheritedObjects
, enumerations
, which will be used to represent "active" objects, and then a deprecated
section that has those same four subgroups to denote, well, "deprecated" objects. The deprecated objects will be subject to later removal.
Given a structure such as:
"attributes": {
"alpha": {
"deprecated": true,
"description": "A description of alpha.",
"dataType": "string"
},
"beta": {
"deprecated": false,
"description": "A description of beta.",
"dataType": "associated object",
"associatedObject": "gamma"
},
"kappa": {
"deprecated": false,
"description": "A description of kappa.",
"dataType": "string"
}
}
}
How might I reorganize the file using jq
to appear more like the following?
"deprecations": {
"attributes": {
"alpha": {
"description": "A description of alpha.",
"dataType": "string"
}
},
"enumerations": {},
"associatedObjects": {},
"inheritedObjects": {}
},
"attributes": {
"kappa": {
"description": "A description of kappa.",
"dataType": "string"
}
},
"enumerations": {},
"associatedObjects": {
"beta": {
"description": "A description of beta.",
"dataType": "gamma"
}
},
"inheritedObjects": {}
}
I've only been able to add the new, empty sections (without any nesting) at the same level as attributes
via jq '.associatedObjects = {} | .inheritedObjects = {} | .enumerations = {} | .deprecations = {} '
I attempted to move the item flagged as deprecated
via this command:
jq '.attributes | keys[] as $k |
if (.[$k].deprecated == true) then
(del(.[$k].deprecated) | .deprecated = .[$k] | del(.[$k]))
else empty end '
but this results in invalid JSON and seems to duplicate the structure. I've also not been able to combine it with the creation of the new sections. It appears I don't have to create those new sections separately and/or beforehand.
What would it take to achieve this goal?
CodePudding user response:
I cannot entirely follow the criteria for your distribution, especially .enumerations
and .inheritedObjects
are unclear, but this could get you going:
.attributes | (map_values(select(.dataType == "string")) | {
deprecations: map_values(select(.deprecated)),
attributes: map_values(select(.deprecated | not))
}) {
associatedObjects: map_values(select(.dataType == "associated object"))
}
{
"deprecations": {
"alpha": {
"deprecated": true,
"description": "A description of alpha.",
"dataType": "string"
}
},
"attributes": {
"kappa": {
"deprecated": false,
"description": "A description of kappa.",
"dataType": "string"
}
},
"associatedObjects": {
"beta": {
"deprecated": false,
"description": "A description of beta.",
"dataType": "associated object",
"associatedObject": "gamma"
}
}
}
CodePudding user response:
This should generate the expected output :
jq '(.attributes | map_values(select(.deprecated))) as $dep
| .depreciations.attributes = ($dep | map_values(del(.deprecated)))
| (.attributes | map_values(select(has("associatedObject")))) as $assoc
| .associatedObjects = ($assoc
| map_values(.dataType = .associatedObject)
| map_values(del(.deprecated, .associatedObject))
)
| .attributes |= del(.[]|select(.deprecated))
| .attributes |= del(.[]|select(has("associatedObject")))
| .attributes[] |= del(.deprecated)
| .depreciations = { "enumerations": {}, "associatedObjects": {}, "inheritedObjects": {} }
| . { "enumerations": {}, "inheritedObjects": {} }
' input.json
{
"attributes": {
"kappa": {
"description": "A description of kappa.",
"dataType": "string"
}
},
"depreciations": {
"attributes": {
"alpha": {
"description": "A description of alpha.",
"dataType": "string"
}
},
"enumerations": {},
"associatedObjects": {},
"inheritedObjects": {}
},
"associatedObjects": {
"beta": {
"description": "A description of beta.",
"dataType": "gamma"
}
},
"enumerations": {},
"inheritedObjects": {}
}