jq - фильтр потока для нескольких значений одного и того же ключа - PullRequest
0 голосов
/ 14 сентября 2018

Я обрабатываю очень большой JSON, в котором мне нужно отфильтровать внутренние объекты JSON, используя значение ключа.Мой JSON выглядит следующим образом:

{"userActivities":{"L3ATRosRdbDgSmX75Z":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-20"},"L3ATSFGrpAYRkIIKqrh":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-21"},"L3AVHvmReBBPNGluvHl":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-22"},"L3AVIcqaDpZxLf6ispK":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday,"localDate":"2018-01-19"}}}

Я хочу поместить фильтр на значения localDate, чтобы localDate в 2018-01-20 или localDate в "2018-01-21", чтобы вывод был похож.

{"userActivities":{"L3ATRosRdbDgSmX75Z":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-20"},"L3ATSFGrpAYRkIIKqrh":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-21"}}}

Я задал подобный вопрос здесь и понял, что мне нужно наложить фильтр на несколько значений и сохранить первоначальную структуру JSON.

https://stackoverflow.com/questions/52324497/how-to-filter-json-using-jq-stream

Заранее огромное спасибо!

1 Ответ

0 голосов
/ 14 сентября 2018

Из поваренной книги jq , давайте заимствуем def atomize(s):

# Convert an object (presented in streaming form as the stream s) into
# a stream of single-key objects
# Examples:
#   atomize({a:1,b:2}|tostream)
#   atomize(inputs) (used in conjunction with "jq -n --stream")
def atomize(s):
  fromstream(foreach s as $in ( {previous:null, emit: null};
      if ($in | length == 2) and ($in|.[0][0]) != .previous and .previous != null
      then {emit: [[.previous]], previous: $in|.[0][0]}
      else { previous: ($in|.[0][0]), emit: null}
      end;
      (.emit // empty), $in) ) ;

Поскольку объект верхнего уровня, описанный в OP, содержит только одну клавишу, мы можем выбрать август 2018 г.следующие объекты:

atomize(1|truncate_stream(inputs))
| select( .[].localDate[0:7] == "2018-08")

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

def add(s): reduce s as $x (null; .+$x);

{"userActivities": add(
    atomize(1|truncate_stream(inputs | select(.[0][0] == "userActivities")))
    | select( .[].localDate[0:7] =="2018-01") ) }

Вариация

Если объект верхнего уровня имеет более одной клавиши, тогда будет подходить следующий вариант:

atomize(1|truncate_stream(inputs | select(.[0][0] == "userActivities")))
| select( .[].localDate[0:7] =="2018-08")
...