Como eu posso analisar o JSON para testar o valor da string de uma chave aninhada?

1

Por exemplo, aqui está a saída do meu programa (bspwm, se você quiser saber):

{
  "id": 29360131,
  "splitType": "vertical",
  "splitRatio": 0.5,
  "birthRotation": 90,
  "vacant": true,
  "sticky": false,
  "private": false,
  "locked": false,
  "presel": null,
  "rectangle": {
    "x": 0,
    "y": 0,
    "width": 1920,
    "height": 1200
  },
  "firstChild": null,
  "secondChild": null,
  "client": {
    "className": "Termite",
    "instanceName": "termite",
    "borderWidth": 1,
    "state": "floating",
    "lastState": "tiled",
    "layer": "normal",
    "lastLayer": "normal",
    "urgent": false,
    "visible": true,
    "icccmFocus": true,
    "icccmInput": true,
    "minWidth": 10,
    "maxWidth": 0,
    "minHeight": 19,
    "maxHeight": 0,
    "wmStatesCount": 0,
    "wmState": [],
    "tiledRectangle": {
      "x": 0,
      "y": 0,
      "width": 958,
      "height": 1198
    },
    "floatingRectangle": {
      "x": 638,
      "y": 394,
      "width": 642,
      "height": 410
    }
  }
}

Quero verificar se "state" não é "tiling" . Nesse caso, é "floating" .

    
por CodeGnome 24.02.2016 / 06:53

4 respostas

2

Usando jq com testes booleanos

Dado que seu JSON é armazenado em uma variável chamada json , você poderia fazer o seguinte no prompt do shell:

$ echo "$json" | jq '.client.state | test("tiling")'
false

Isso retorna corretamente false porque o seu corpus contém o valor floating .

Testes negativos

Como alternativa, se você quiser testar se o valor não é tiling , você pode usar o filtro | not para negar a lógica do seu teste. Por exemplo:

$ echo "$json" | jq '.client.state | test("tiling") | not'
true

Isso retorna true porque o estado do cliente não é tiling , é floating .

Extraindo o valor

Caso deseje garantir que seus filtros estejam funcionando de maneira sã, você também pode usar jq para analisar o valor dessa chave aninhada. Por exemplo:

$ echo "$json" | jq .client.state
"floating"

Você pode então usar essa informação para validar seus testes e filtros, ou simplesmente passá-la ao longo de um pipeline de shell para fgrep ou fgrep -v se você não se importa em gerar um processo adicional.

    
por 24.02.2016 / 08:50
1

A melhor opção é usar um analisador JSON.

Se você insistir em usar grep :

Assumindo que seu grep suporta PCRE ( -P ):

bspwm | grep -Po '"state":\K[^,]*'

Isto irá obter o valor (com aspas) da chave "state" .

Se você não quiser colocar aspas em torno da chave:

bspwm | grep -Po '"state":"\K[^"]*'

Por exemplo:

% grep -Po '"state":\K[^,]*' <<<'{"id":29360131,"splitType":"vertical","splitRatio":0.500000,"birthRotation":90,"vacant":true,"sticky":false,"private":false,"locked":false,"presel":null,"rectangle":{"x":0,"y":0,"width":1920,"height":1200},"firstChild":null,"secondChild":null,"client":{"className":"Termite","instanceName":"termite","borderWidth":1,"state":"floating","lastState":"tiled","layer":"normal","lastLayer":"normal","urgent":false,"visible":true,"icccmFocus":true,"icccmInput":true,"minWidth":10,"maxWidth":0,"minHeight":19,"maxHeight":0,"wmStatesCount":0,"wmState":[],"tiledRectangle":{"x":0,"y":0,"width":958,"height":1198},"floatingRectangle":{"x":638,"y":394,"width":642,"height":410}}'

"floating"


% grep -Po '"state":"\K[^"]*' <<<'{"id":29360131,"splitType":"vertical","splitRatio":0.500000,"birthRotation":90,"vacant":true,"sticky":false,"private":false,"locked":false,"presel":null,"rectangle":{"x":0,"y":0,"width":1920,"height":1200},"firstChild":null,"secondChild":null,"client":{"className":"Termite","instanceName":"termite","borderWidth":1,"state":"floating","lastState":"tiled","layer":"normal","lastLayer":"normal","urgent":false,"visible":true,"icccmFocus":true,"icccmInput":true,"minWidth":10,"maxWidth":0,"minHeight":19,"maxHeight":0,"wmStatesCount":0,"wmState":[],"tiledRectangle":{"x":0,"y":0,"width":958,"height":1198},"floatingRectangle":{"x":638,"y":394,"width":642,"height":410}}'

floating
    
por 24.02.2016 / 07:25
1

Usar um analisador JSON dedicado, como o Jshon , é uma abordagem mais robusta:

jshon -e client -e state -u < file             
floating
    
por 24.02.2016 / 07:38
0

outra alternativa fácil para extrair informações de JSON e testá-las é a ferramenta jtc (supondo que o source json esteja em file.json ):

bash $ cat file.json | jtc -w "[state]:<tiling>" | grep "tiling" >/dev/null; if [ $? == 0 ]; then echo "true"; else echo "false"; fi;
false
bash $ 
bash $ cat file.json | jtc -w "[state]:<floating>" | grep "floating" >/dev/null; if [ $? == 0 ]; then echo "true"; else echo "false"; fi;
true
bash $ 
    
por 12.11.2018 / 23:23