Agregue la variable bash como clave JSON y valor al objeto

Agregue la variable bash como clave JSON y valor al objeto

Tengo una matriz JSON de objetos como este.

[
  {
    "id" : "tmp1387816934708382026",
    "owner" : "john",
    "x11-display" : ":5",
    "x11-authority" : "/run/user/john/dcv/tmp1387816934708382026.xauth",
    "num-of-connections" : 1,
    "creation-time" : "2019-05-14T14:12:14.989287Z",
    "last-disconnection-time" : "2019-05-31T18:58:42.851223Z"
  },
  {
    "id" : "tmp4241942441012516520",
    "owner" : "mike",
    "x11-display" : ":10",
    "x11-authority" : "/run/user/mike/dcv/tmp4241942441012516520.xauth",
    "num-of-connections" : 0,
    "creation-time" : "2019-05-17T16:23:05.891531Z",
    "last-disconnection-time" : "2019-05-19T11:23:30.844797Z"
  }
]

Necesito agregar una clave nombrada days-idlecon un valor a cada objeto que se calcula dentro de mi script bash. Esto es lo que busco en cada objeto JSON.

{
    "id" : "tmp1387816934708382026",
    "owner" : "mike",
    "x11-display" : ":5",
    "x11-authority" : "/run/user/mike/dcv/tmp1387816934708382026.xauth",
    "num-of-connections" : 1,
    "creation-time" : "2019-05-14T14:12:14.989287Z",
    "last-disconnection-time" : "2019-05-31T18:58:42.851223Z",
    "days-idle" : "$daysIdle"
  }

Sé que puedes agregar una clave, jqpero no estaba seguro de cómo agregar un par clave-valor donde el valor es una variable bash.

Respuesta1

Suponiendo que desea agregar su nueva clave al elemento con un .idvalor particular $id:

jq --arg id "$id" --arg idle "$daysIdle" \
    '( .[] | select(.id == $id)."days-idle" ) |= $idle' file

Esto selecciona el elemento de la matriz con el .idque queremos modificar, luego agrega (en realidadactualizaciones) la ."days-idle"clave de ese elemento con el valor particular que queremos que tenga.

Si ."days-idle"debería ser el tiempo entre la ."last-disconnection-time"marca de tiempo yahora, luego puedes actualizar todos los elementos en el JSON de esta manera:

jq 'def dayssince: ((now - (sub("[.].*"; "Z") | fromdate))/86400) | round;
    map(. += { "days-idle": (."last-disconnection-time" | dayssince) })' file

La sub()llamada truncará la marca de tiempo en el punto y reemplazará el final con Z. Esto se debe a fromdateque es un poco restrictivo en el tipo de marcas de tiempo que puede analizar y no maneja la precisión de menos de un segundo de la cadena de marca de tiempo original.

Decidí poner el cálculo real del número de días desde la marca de tiempo como una jqfunción llamada dayssince, solo para mantener el código ordenado.

El JSON resultante (cuando se ejecutó el 28 de junio de 2021):

[
  {
    "id": "tmp1387816934708382026",
    "owner": "john",
    "x11-display": ":5",
    "x11-authority": "/run/user/john/dcv/tmp1387816934708382026.xauth",
    "num-of-connections": 1,
    "creation-time": "2019-05-14T14:12:14.989287Z",
    "last-disconnection-time": "2019-05-31T18:58:42.851223Z",
    "days-idle": 759
  },
  {
    "id": "tmp4241942441012516520",
    "owner": "mike",
    "x11-display": ":10",
    "x11-authority": "/run/user/mike/dcv/tmp4241942441012516520.xauth",
    "num-of-connections": 0,
    "creation-time": "2019-05-17T16:23:05.891531Z",
    "last-disconnection-time": "2019-05-19T11:23:30.844797Z",
    "days-idle": 771
  }
]

Respuesta2

Primero, voy a asumir que tienes la matriz de objetos JSON en una variable Bash, así que comencemos con eso:

bash$ object='[
  {
    "id" : "tmp1387816934708382026",
    "owner" : "john",
    "x11-display" : ":5",
    "x11-authority" : "/run/user/john/dcv/tmp1387816934708382026.xauth",
    "num-of-connections" : 1,
    "creation-time" : "2019-05-14T14:12:14.989287Z",
    "last-disconnection-time" : "2019-05-31T18:58:42.851223Z"
  },
  {
    "id" : "tmp4241942441012516520",
    "owner" : "mike",
    "x11-display" : ":10",
    "x11-authority" : "/run/user/mike/dcv/tmp4241942441012516520.xauth",
    "num-of-connections" : 0,
    "creation-time" : "2019-05-17T16:23:05.891531Z",
    "last-disconnection-time" : "2019-05-19T11:23:30.844797Z"
  }
]'

A continuación, asumiré que $daysIdletambién es variable y contiene un número:

bash$ daysIdle=3

Ahora, podemos repetir el $objectpaso jqpara agregar esa variable.

bash$ echo "$object" | jq --arg daysIdle "$daysIdle" '.[]."days-idle" = ($daysIdle | tonumber)'

Algunas notas importantes al respecto. Si los objetos están realmente en un archivo o provienen de algún otro flujo como cURL, simplemente reemplácelos echo $objectpor lo que sea apropiado. En segundo lugar, supongo que lo desea como un número JSON y no como una cadena que --argnormalmente se crea, por lo que tengo un filtro para solucionarlo. Por último, tenga en cuenta que uso la --argopción para jqpasar el valor. Esto es mucho mejor y más seguro que intentar incrustar el valor en la cadena del filtro JSON y no provocará un error de sintaxis. Generará un error si no puede convertir a un número, pero no permitirá la inyección arbitraria en la cadena del filtro. Dicho esto, veamos el resultado:

[
  {
    "id": "tmp1387816934708382026",
    "owner": "john",
    "x11-display": ":5",
    "x11-authority": "/run/user/john/dcv/tmp1387816934708382026.xauth",
    "num-of-connections": 1,
    "creation-time": "2019-05-14T14:12:14.989287Z",
    "last-disconnection-time": "2019-05-31T18:58:42.851223Z",
    "days-idle": 3
  },
  {
    "id": "tmp4241942441012516520",
    "owner": "mike",
    "x11-display": ":10",
    "x11-authority": "/run/user/mike/dcv/tmp4241942441012516520.xauth",
    "num-of-connections": 0,
    "creation-time": "2019-05-17T16:23:05.891531Z",
    "last-disconnection-time": "2019-05-19T11:23:30.844797Z",
    "days-idle": 3
  }
]

información relacionada