jq: сортировать значения объектов

#json #jq

#json #jq

Вопрос:

Я хочу отсортировать эту структуру данных по ключам объекта (легко с -S и отсортировать значения объектов (массивы) по свойству ‘foo’.

Я могу отсортировать их с помощью

 jq -S '
  . as $in
  | keys[]
  | . as $k
  | $in[$k] | sort_by(.foo)
    ' < test.json
  

… но при этом теряются ключи.

Я пробовал варианты добавления | { "($k)": . } , но в итоге получаю список объектов вместо одного объекта. Я также пробовал варианты добавления в $ in (та же проблема) или использования $in = $in * { ... } , но это приводит к синтаксическим ошибкам.

Единственное решение, которое я нашел, состояло в том, чтобы просто иметь отдельные объекты, а затем передавать их в jq -s add , но … Я действительно хотел, чтобы это работало по-другому. 🙂

Тестовые данные ниже:

 {
    "": [
        { "foo": "d" },
        { "foo": "g" },
        { "foo": "f" }
    ],
    "c": [
        { "foo": "abc" },
        { "foo": "def" }
    ],
    "e": [
        { "foo": "xyz" },
        { "foo": "def" }
    ],
    "ab": [
        { "foo": "def" },
        { "foo": "abc" }
    ]
}
  

Ответ №1:

Может быть, это?

 jq -S '.[] |= sort_by(.foo)'
  

Вывод

 {
  "": [
    {
      "foo": "d"
    },
    {
      "foo": "f"
    },
    {
      "foo": "g"
    }
  ],
  "ab": [
    {
      "foo": "abc"
    },
    {
      "foo": "def"
    }
  ],
  "c": [
    {
      "foo": "abc"
    },
    {
      "foo": "def"
    }
  ],
  "e": [
    {
      "foo": "def"
    },
    {
      "foo": "xyz"
    }
  ]
}
  

Комментарии:

1. приятно, что это короче, чем другое, которое я предложил (опубликовано отдельно). Меня смущает, что .[] | в вашем решении не «теряются данные». Я предполагаю, что jq модель данных мне совсем не понятна, и я все еще слишком много думаю о ней как о обычном языке программирования, где я должен возвращать данные по мере необходимости.

2. Я думаю, что ручной ввод в операторе присваивания обновлений поможет.

Ответ №2:

у @user197693 был отличный ответ. Предложение, которое я получил в личном сообщении в другом месте, состояло в том, чтобы использовать

 jq -S 'with_entries(.value |= sort_by(.foo))'
  

Ответ №3:

Если по какой-либо причине использование опции -S командной строки не является удовлетворительным вариантом, вы также можете выполнить сортировку по ключу, используя to_entries | sort_by(.key) | from_entries идиому. Таким образом, полное решение проблемы было бы:

 .[] |= sort_by(.foo)
| to_entries | sort_by(.key) | from_entries