Como posso excluir todas as chaves com um valor específico dentro de um JSON com jq?

Como posso excluir todas as chaves com um valor específico dentro de um JSON com jq?

Digamos que eu tenha um JSON como o seguinte:

{
    "key1": {
        "keyA": "1",
        "keyB": "null",
        "keyC": "null"
    },
    "key2": {
        "keyA": "null",
        "keyB": "3",
        "keyC": "null"
    }
}

Gostaria de encontrar uma maneira de excluir todas as chaves com o valor nullno meu JSON. Então o resultado seria o seguinte:

{
    "key1": {
        "keyA": "1"
    },
    "key2": {
        "keyB": "3"
    }
}

Eu sei que posso excluir chaves específicas com seus nomes usando jq, por exemplo cat myjson.json | jq 'del(.[]|.keyA)', isso apagará todas as minhas keyAchaves dentro do json, mas quero excluir as chaves de acordo com seus valores... Como posso excluir todas as chaves com valor "null"usando jq?

Responder1

del(..|select(. == "null"))

Isso usa ooperador de descida recursiva..eselectfunçãopara encontrar todos os locais em qualquer lugar do objeto com valores iguais "null"e fornecê-los a del. selectavalia uma expressão booleana para decidir se deve incluir um valor específico ou não, enquanto ..fornece a ela todos os valores da árvore e delaceita qualquer expressão que produza localizações, o que ocorre. (demonstração)

Você pode usar a pathfunção para verificar o que está encontrando:

path(..|select(. == "null"))

e depure o que você acha que você está tentando excluir primeiro. Osaídaé uma matriz de chaves a serem seguidas recursivamente para atingir o valor e, portanto, o item final da matriz é a chave que realmente seria excluída.

Você também pode usar update-assignment |= emptyno jq 1.6 e superior (ele falha silenciosamente em versões anteriores). Você pode ou não achar isso mais claro: (..|select(. == "null")) |= empty(demonstração) exclui essas mesmas chaves.


Se seus valores forem true nulls, em vez de string "null", você pode usar a nullsfunção interna no lugar do inteiro select: del(..|nulls).

Se seus valores forem verdadeiros nulosevocê está usandojq 1,5(a versão atual em muitas distribuições), você precisará usar recurse(.[]?; true)no lugar de ... Isso ocorre porque os valores nulos são especificamente excluídos ..(porqueé definido comorecurse, qualé definido como recurse(.[]?), que é definido como recurse(.[]?; . != null)). Este comportamento mudou para o (mais útil) acima em 1.6, emboraa documentaçãonão mudou, o queparece ser um bug de documentação.

Responder2

Supondo que você saiba que deseja testar os valores no 2º nível:

jq 'del(.[][] | select(. == "null"))' file

Isso exclui todos os pares de valores-chave no segundo nível a partir do topo, onde o valor é a string literal null.

Dado o documento em questão, isso produz o resultado esperado.

Usando uma versão jqmais recente que 1.5, você também pode atualizar os dados para os bits que não possuem o nullvalor:

jq '.[][] |= select(. != "null")' file

informação relacionada