Use jq to filter JSON based the existance of a nested array and the value of items nested within it

Derek Beattie :

Given the following JSON,

I'm trying to filter out items in the cars array where the item's comments array is null:

.cars[] |  select(.comments == null)

or the item's comments array exists and any of the comments objects don't contain the value "FooBar"

.cars[] |  select( select(.comments != null) | (any(.comments[]; index("FooBar")) | not) )

while retaining the original structure.

With jq I can figure out how to create the critera I want to filter down to but what I can't wrap my head around is how to make that apply to the top level items.

JSON input:

{
    "person": {
        "first_name": "Bob",
        "last_name": "Smith"
    },
    "addresses": [
        {
            "home": {
                "line1": "123",
                "line2": "A st."
            }
        },
        {
            "work": {
                "line1": "456",
                "line2": "B st."
            }
        }
    ],
    "cars": [
        {
            "make": "Honda",
            "model": "Civic"
        },
        {
            "make": "Honda",
            "model": "Accord"
        },
        {
            "make": "Honda",
            "model": "Pilot",
            "comments": [
                "Comment 1",
                "Comment 2",
                "FooBar"
            ]
        },
        {
            "make": "Honda",
            "model": "Passport",
            "comments": [
                "Comment 3",
                "Comment 4"
            ]
        }
    ]
}

JSON Outut, same as the input but the oject with the comment array containg the value "FooBar" is filtered out:

{
    "person": {
        "first_name": "Bob",
        "last_name": "Smith"
    },
    "addresses": [
        {
            "home": {
                "line1": "123",
                "line2": "A st."
            }
        },
        {
            "work": {
                "line1": "456",
                "line2": "B st."
            }
        }
    ],
    "cars": [
        {
            "make": "Honda",
            "model": "Civic"
        },
        {
            "make": "Honda",
            "model": "Accord"
        },
        {
            "make": "Honda",
            "model": "Passport",
            "comments": [
                "Comment 3",
                "Comment 4"
            ]
        }
    ]
}
oguz ismail :

Just use the update-assignment operator (|=).

.cars |= map(select(.comments))
.cars |= map(select(.comments and any(.comments[]; index("FooBar")) | not))

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=33121&siteId=1