Adicione a variável bash como chave JSON e valor no objeto

Adicione a variável bash como chave JSON e valor no objeto

Eu tenho uma matriz JSON de objetos assim.

[
  {
    "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"
  }
]

Preciso adicionar uma chave nomeada days-idlecom um valor para cada objeto calculado dentro do meu script bash. É isso que procuro em 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"
  }

Eu sei que você pode adicionar uma chave, jqmas não tinha certeza de como adicionar um par de chave e valor onde o valor é uma variável bash.

Responder1

Supondo que você queira adicionar sua nova chave ao elemento com um .idvalor específico $id:

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

Isso seleciona o elemento da matriz com o .idque queremos modificar e depois adiciona (na verdadeatualizações) a ."days-idle"chave desse elemento com o valor específico que queremos que ele tenha.

Deve ."days-idle"ser o tempo entre o ."last-disconnection-time"carimbo de data/hora eagora, então você pode atualizar todos os elementos no JSON assim:

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

A sub()chamada truncará o carimbo de data/hora no ponto e substituirá o final dele por Z. Isso se deve ao fato de fromdateser um pouco restritivo no tipo de carimbo de data/hora que ele pode analisar e não manipula a precisão de menos de um segundo da string de carimbo de data/hora original.

Decidi colocar o cálculo real do número de dias desde o timestamp como uma jqfunção chamada dayssince, apenas para manter o código organizado.

O JSON resultante (quando executado em 28 de junho 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
  }
]

Responder2

Primeiro, vou assumir que você tem o array de objetos JSON em uma variável Bash, então vamos começar com isso:

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 seguir, assumirei que $daysIdletambém é variável e contém um número:

bash$ daysIdle=3

Agora, podemos repetir o $objectthrough jqpara adicionar essa variável.

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

Algumas notas importantes sobre isso. Se os objetos estiverem realmente em um arquivo ou vindo de algum outro fluxo como cURL, basta substituir echo $objecto que for apropriado. Em segundo lugar, presumo que você o queira como um número JSON e não como uma string que --argnormalmente é criada, então tenho um filtro para corrigir isso. Por último, observe que utilizo a --argopção para jqpassar o valor. Isso é muito melhor e mais seguro do que tentar incorporar o valor na própria string do filtro JSON e não causará um erro de sintaxe nela. Irá gerar um erro se não puder converter para um número, mas não permitirá a injeção arbitrária na string do filtro. Dito isso, vamos ver o 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
  }
]

informação relacionada