2016-03-29 2 views
2

У меня есть JSON-файл, который выглядит следующим образом (грубая схемы):JQ: выберите не понижая элементы из массива

[{ 
    "custom_variables": [ 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "profile_id", 
      "value": "123" 
     } 
    ], 
    // many fields 
    "xxx": "xxx", 
    "xxx": "xxx", 
    "xxx": "xxx" 
}] 

Я использую JQ, чтобы извлечь все поля из объекта верхнего уровня. Поле custom_variables представляет собой массив объектов с именем и значением.

Я хочу извлечь конкретный объект из custom_variables, учитывая его имя.

Так что я делаю это:

jq 'map(
    { 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .custom_variables | .[] | select(.name == "variable_name") 
    } 
)' 

Это почти работает; он получает переменную, которую я хочу, когда она существует, но когда она этого не делает (или если custom_variables сама не делает этого), она потеряет весь объект верхнего уровня. Поэтому, в конце концов, я получаю меньше объектов, чем я вставлял в скрипт.

Как я могу просто вернуть значение null, если я не нахожу это поле, но сохраняю остальную часть данных?

ответ

0

Это работает, но выглядит некрасиво. Какие-нибудь лучшие решения?

custom_variables: (if (.custom_variables | length > 0) 
      then (.custom_variables | .[]? | select(.name == "variable_name") | .value | scan("\\d+")) 
      else null 
      end) 
1

Использовать альтернативный оператор (//), чтобы превратить поток нулевых элементов (таких, как те, которые могут быть сгенерированы select или .[]) в значение:

jq 'map(
    { 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .custom_variables | .[] | select(.name == "variable_name") // null 
    } 
)' 

Это будет иметь .xxx быть null, когда поток с нулевым элементом находится слева от //.

Вы можете, конечно, место альтернативного оператора в другом месте, чтобы захватить поток нулевого элемента на более ранней или более поздней стадии, например, на уровне объекта:

jq 'map(
    { 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .xxx, 
     xxx: .custom_variables | .[] | select(.name == "variable_name") 
    } // {} 
)' 
0

Следующая делает что вы указали, что хотите, насколько я могу понять ваши требования .

map(if .custom_variables 
    then .custom_variables |= (map(select(.name == "variable_name") | .value) 
           | .[0]) 
    else . 
    end) 

Пример входных данных:

[{ 
    "custom_variables": [ 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "xxx", 
      "value": "xxx" 
     }, 
     { 
      "name": "variable_name", 
      "value": "123" 
     } 
    ], 
    "xxx1": "xxx", 
    "xxx2": "xxx", 
    "xxx3": "xxx" 
}, 

{ 
    "yyy1": "yyy", 
    "yyy2": "yyy", 
    "yyy3": "yyy" 
} 
] 

Выход:

[ 
    { 
    "custom_variables": "123", 
    "xxx1": "xxx", 
    "xxx2": "xxx", 
    "xxx3": "xxx" 
    }, 
    { 
    "yyy1": "yyy", 
    "yyy2": "yyy", 
    "yyy3": "yyy" 
    } 
] 
Смежные вопросы