фильтровать определенные (под) ключи по значению JSON - PullRequest
3 голосов
/ 07 мая 2020

У меня есть относительно большой JSON файл, содержащий много данных, которые мне не нужны.

Я хотел бы просто сохранить элементы, которые меня интересуют, но я хочу сохранить общие структура.

[
  {
    "name"  : "foo",
    "age"   : 12,
    "weight": 23, 
    "colors": {
      "head":{
        "hair": "blue",
        "eyes": "green"
      }
    }
  },
  {
    "name"  : "bar",
    "age"   : 42,
    "weight": 54, 
    "colors": {
      "head":{
        "hair": "blue",
        "eyes": "blue"
      }
    }
  },
  {
    "name"  : "baz",
    "age"   : 65,
    "weight": 439, 
    "colors": {
      "head":{
        "hair": "green",
        "eyes": "red"
      }
    }
  }

]

Результат должен выглядеть так:

{
  "name": "foo",
  "colors": {
    "head": {
      "eyes": "green"
    }
  }
}
{
  "name": "bar",
  "colors": {
    "head": {
      "eyes": "blue"
    }
  }
}
{
  "name": "baz",
  "colors": {
    "head": {
      "eyes": "red"
    }
  }
}

Мой фактический входной объект имеет ~ 100 листовых ключей на объект верхнего уровня, и мне нужно ~ 10 и почти все на разных уровнях иерархии.

Я изучил некоторые API-интерфейсы обработки json (например, javascript, loda sh и jq) и не смог найти такой механизм. В основном они полагаются на создание новых объектов в простом синтаксисе, что требует создания объекта с нуля.

Например:

jq '[.[]| {name: .name, colors:{head:{eyes: .colors.head.eyes}}}]'

с глубокими иерархиями это немного запутано. * Пропустил ли я что-то, что позволяет упростить определение ключей глубоких объектов, например:

.[] | {name: .name, colors.head.eyes = .colors.head.eyes}

, или еще более удобных: какой-то механизм фильтрации дополнительных ключей, например

.[] | filteKeys(["name", "colors.head.eyes"])

Я бы предпочел какую-то команду строчная программа, поэтому я попробовал с JQ.

1 Ответ

3 голосов
/ 07 мая 2020

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

def pick(paths):
  . as $in
  | reduce path(paths) as $path (null;
    setpath($path; $in | getpath($path))
  );

И вы можете использовать его как:

.[] | pick(.name, .colors.head.eyes)

демонстрация на jqplay.org

...