¿Cómo puedo excluir todas las claves con un valor específico dentro de un JSON con jq?

¿Cómo puedo excluir todas las claves con un valor específico dentro de un JSON con jq?

Digamos que tengo un JSON como el siguiente:

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

Me gustaría encontrar una manera de excluir todas las claves con el valor nullen mi JSON. Entonces el resultado sería el siguiente:

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

Sé que puedo excluir claves específicas con sus nombres usando jq, por ejemplo cat myjson.json | jq 'del(.[]|.keyA)', esto borrará todas mis keyAclaves dentro del json, pero quiero excluir las claves según sus valores... ¿Cómo puedo excluir todas las claves con valor "null"usando jq?

Respuesta1

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

Esto utiliza eloperador de descenso recursivo..yselectfunciónpara encontrar todas las ubicaciones en cualquier parte del objeto con valores que sean iguales "null"y les proporcione del. selectevalúa una expresión booleana para decidir si incluye un valor particular o no, mientras ..le asigna cada valor en el árbol y delacepta cualquier expresión que produzca ubicaciones, lo cual hace. (manifestación)

Puede utilizar la pathfunción para comprobar lo que está encontrando:

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

y depura lo que cree que estás intentando eliminar primero. Elproducciónes una matriz de claves a seguir de forma recursiva para alcanzar el valor, por lo que el elemento final de la matriz es la clave que realmente se eliminaría.

También puede usar update-assignment |= emptyen jq 1.6 y versiones posteriores (falla silenciosamente en versiones anteriores). Puede que esto le resulte más claro o no: (..|select(. == "null")) |= empty(manifestación) elimina esas mismas claves.


Si sus valores son true nulls, en lugar de la cadena "null", puede usar la nullsfunción incorporada en lugar del conjunto select:.del(..|nulls)

Si sus valores son verdaderos nulosyestas usandojq 1.5(la versión actual en muchas distribuciones), necesitarás usar recurse(.[]?; true)en lugar de ... Esto se debe a que los valores nulos están específicamente excluidos ..(porquese define comorecurse, cualSe define como recurse(.[]?), que se define como recurse(.[]?; . != null)). Este comportamiento cambió al (más útil) anterior en 1.6, aunquela documentaciónno ha cambiado, lo cualparece ser un error de documentación.

Respuesta2

Suponiendo que sabe que desea probar los valores en el segundo nivel:

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

Esto elimina todos los pares clave-valor en el segundo nivel desde arriba, donde el valor es la cadena literal null.

Dado el documento en la pregunta, esto produce el resultado esperado.

Usando una versión jqposterior a la 1.5, también puedes actualizar los datos a los bits que no tienen el nullvalor:

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

información relacionada