2017-01-20 8 views
2

Вот пример ответа JSON из моего завитка:Числовой аргумент, передаваемый с JQ не --arg соответствие данных с ==

{ 
    "success": true, 
    "message": "jobStatus", 
    "jobStatus": [ 
    { 
     "ID": 9, 
     "status": "Successful" 
    }, 
    { 
     "ID": 2, 
     "status": "Successful" 
    }, 
    { 
     "ID": 99, 
     "status": "Failed" 
    } 
    ] 
} 

Я хочу, чтобы проверить состояние ID = 2. Вот команда, я попробовал:

cat test.txt|jq --arg v "2" '.jobStatus[]|select(.ID == $v)|.status' 

ответ: нет ни

Я попробовал значение 2 без кавычек и до сих пор нет результата.

В противоположность этому, если я пытаюсь команду с буквального2, он работает:

cat test.txt | jq '.jobStatus[]|select(.ID == 2)|.status' 

ответ:

"Successful" 

я застрял. Может ли кто-нибудь помочь мне определить проблему?

ответ

5

jq это данные типа, известно:

  • .ID, как это определено в ввода JSON, является номер,

  • но любой аргумент командной строки, прошедший с --arg (такой как v здесь), неизменно является Строка (цитирую ли значение или нет),

так, чтобы сравнить их, вы должны использовать явное преобразование типа, например, с tonumber/1:

jq --arg v '2' '.jobStatus[] | select(.ID == ($v | tonumber)) | .status' test.txt 

С учетом того, что вы передаете только скаляр здесь, следующее решение: --argjson (jq v1.5 +) является немного излишним, но это альтернатива преобразования явного типа в том, что передавая JSON аргумент в действительности проходит набран данные:

jq --argjson v '{ "ID": 2 }' '.jobStatus[] | select(.ID == $v.ID) | .status' test.txt 

peak's answer демонстрирует, что даже --argjson v 2 работает (в этом случае по сравнению с $v работает напрямую), что, безусловно, больше всего concis е решение, но может потребоваться объяснение:

  • Даже если 2 не может выглядеть как JSON, это: это допустимый текст JSON, содержащий один значение типа числа (см. json.org).

    • В частности, это тот факт, что 2 является неупомянут маркера, который начинается с цифрой , что делает его число в контексте JSON (The JSON строки -value эквивалента "2" , который из оболочки должен быть передан как '"2"' - обратите внимание на встроенные двойные кавычки).
  • Поэтому jq интерпретирует --argjson -v 2 как числа и сравнение .ID == $v работает, как предполагалось (обратите внимание, что то же самое относится и к --argjson -v '2'/--argjson -v "2", где оболочка удаляет кавычки, прежде чем jq видит ценность).
    В отличие от всего, что вы передаете с --arg, всегда есть строка , которая используется как есть.

  • Другими словами: --argjson, целью которого является принимают произвольные тексты JSON в виде строк (например, '{ "ID": 2 }' в приведенном выше примере), также может быть использован для передачи артикула строка-скаляры, чтобы заставить их интерпретация чисел.
    Такая же техника также работает с булевыми строками true и false.


Наконечник шляпы peak за его помощь.

3

Предполагая, что вы хотите проверить значение JSON 2, у вас есть выбор - преобразовать аргумент -arg в число или использовать --argjson с числовым аргументом.Эти альтернативы иллюстрируются следующим образом:

jq --arg v 2 '.jobStatus[] | select(.ID == ($v|tonumber) | .status' 

jq --argjson v 2 '.jobStatus[] | select(.ID == $v) | .status' 

Обратите внимание, что --argjson требует относительно недавнюю версию jq.

Конечно, если вы хотите, чтобы «нормализовать» .id так, что он всегда обрабатывается как строка, вы можете написать:

jq --arg v 2 '.jobStatus[] | select((.ID|tostring) == $v) | .status'