Saltar al contenido

Accediendo a un objeto JSON en Bash – asociativo array / lista / otro modelo

Investigamos en todo el mundo on line y de este modo mostrarte la respuesta a tu problema, si tienes preguntas déjanos tu duda y responderemos porque estamos para ayudarte.

Solución:

Si quieres key y valor, y basado en ¿Cómo convierto un objeto json a key= formato de valor en JQ, puede hacer:

$ jq -r "to_entries|map("(.key)=(.value|tostring)")|.[]" file
SALUTATION=Hello world
SOMETHING=bla bla bla Mr. Freeman

De una manera más general, puede almacenar los valores en un array myarray[key] = value así, simplemente proporcionando jq al while con el while ... do; ... done < <(command) sintaxis:

declare -A myarray
while IFS="=" read -r key value
do
    myarray[$key]="$value"
done < <(jq -r 'to_entries|map("(.key)=(.value)")|.[]' file)

Y luego puede recorrer los valores de esta manera:

for key in "$!myarray[@]"
do
    echo "$key = $myarray[$key]"
done

Para esta entrada dada, devuelve:

SALUTATION = Hello world
SOMETHING = bla bla bla Mr. Freeman

Aunque se respondió esta pregunta, no pude satisfacer completamente mis requisitos con la respuesta publicada. Aquí hay una pequeña reseña que ayudará a los recién llegados a bash.

Presciencia

Un asociativo básico array declaración

#!/bin/bash

declare -A associativeArray=([key1]=val1 [key2]=val2)

También puede utilizar comillas (', ") alrededor de declaration, su keys, y
values.

#!/bin/bash

declare -A 'associativeArray=([key1]=val1 [key2]=val2)'

Y puedes delimitar cada uno [key]=value emparejar a través de espacio o nueva línea.

#!/bin/bash

declare -A associativeArray([key1]=value1
  ['key2']=value2 [key3]='value3'
  ['key4']='value2'               ["key5"]="value3"


  ["key6"]='value4'
  ['key7']="value5"
)

Dependiendo de la variación de su cotización, es posible que deba escapar de su string.

Usando Indirection para acceder a ambos key y valor en un asociativo array

example () 
  local -A associativeArray=([key1]=val1 [key2]=val2)

  # print associative array
  local key value
  for key in "$!associativeArray[@]"; do
    value="$associativeArray["$key"]"
    printf '%s = %s' "$key" "$value"
  done

Ejecutando la función de ejemplo

$ example
key2 = val2
key1 = val1

Conocer los datos mencionados anteriormente le permite derivar los siguientes fragmentos:


Los siguientes ejemplos tendrán todos el resultado del ejemplo anterior.

Evaluación de cadenas

#!/usr/bin/env bash

example () 
  local arrayAsString='associativeArray=([key1]=val1 [key2]=val2)'
  local -A "$arrayAsString"

  # print associative array

Canalizando su JSON en JQ

#!/usr/bin/env bash
# Note: usage of single quotes instead of double quotes for the jq
#       filter. The former is preferred to avoid issues with shell 
#       substitution of quoted strings.
example ()  map("[(.key)]=(.value)") 

jq -n / -null-opción de entrada + --argfile && redirección

#!/usr/bin/env bash

example () @sh)]

Revisar respuestas anteriores

@ Ján Lalinský

Para cargar un objeto JSON en un bash asociativo array de manera eficiente (sin usar bucles en bash), se puede usar la herramienta 'jq', de la siguiente manera.

# first, load the json text into a variable:
json='"SALUTATION": "Hello world", "SOMETHING": "bla bla bla Mr. Freeman"'

# then, prepare associative array, I use 'aa':
unset aa
declare -A aa

# use jq to produce text defining name:value pairs in the bash format
# using @sh to properly escape the values
aacontent=$(jq -r '. | to_entries | .[] | "["" + .key + ""]=" + (.value | @sh)' <<< "$json")

# string containing whole definition of aa in bash
aadef="aa=($aacontent)"

# load the definition (because values may contain LF characters, aadef must be in double quotes)
eval "$aadef"

# now we can access the values like this: echo "$aa[SOMETHING]"

Advertencia: esto usa eval, que es peligroso si la entrada json es de una fuente desconocida (puede contener comandos de shell maliciosos que eval puede ejecutar).

Esto podría reducirse a lo siguiente

example ()  to_entries 

@fedorqui

Si quieres key y valor, y basado en ¿Cómo convierto un objeto json a key= formato de valor en JQ, puede hacer:

$ jq -r "to_entries|map("(.key)=(.value|tostring)")|.[]" file
SALUTATION=Hello world
SOMETHING=bla bla bla Mr. Freeman

De una manera más general, puede almacenar los valores en un array myarray[key] = value así, simplemente proporcionando jq al while con el while ... do; ... done < <(command) sintaxis:

declare -A myarray
while IFS="=" read -r key value
do
    myarray[$key]="$value"
done < <(jq -r "to_entries|map("(.key)=(.value)")|.[]" file)

Y luego puede recorrer los valores de esta manera:

for key in "$!myarray[@]"
do
    echo "$key = $myarray[$key]"
done

Para esta entrada dada, devuelve:

SALUTATION = Hello world
SOMETHING = bla bla bla Mr. Freeman

La principal diferencia entre esta solución y la mía es recorrer el
array en bash o en jq.

Cada solución es válida y, dependiendo de su caso de uso, una puede ser más útil que la otra.

Contexto: esta respuesta se escribió para responder a un título de pregunta que ya no existe..


La pregunta del OP en realidad describe objetos, frente a matrices.

Para asegurarnos de que ayudamos a otras personas que vienen Realmente Sin embargo, si busca ayuda con las matrices JSON, vale la pena cubrirlas explícitamente.


Para el caso seguro donde las cadenas no pueden contener líneas nuevas (y cuando se usa bash 4.0 o más reciente), esto funciona:

str='["Hello world", "bla bla bla Mr. Freeman"]'
readarray -t array <<<"$(jq -r '.[]' <<<"$str")"

Para admitir versiones anteriores de bash y cadenas con nuevas líneas, nos volvemos un poco más elegantes, utilizando una secuencia delimitada por NUL para leer jq:

str='["Hello world", "bla bla bla Mr. Freeman", "this isntwo lines"]'
array=( )
while IFS= read -r -d '' line; do
  array+=( "$line" )
done < <(jq -j '.[] | (. + "u0000")')

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *