Удалить дубликаты в файле JSON

Я пытаюсь отредактировать файл json, чтобы печатать только те подгруппы, у которых есть какие-либо атрибуты, помеченные как «изменить»: false.

Json ниже:

{"group":{
    "subgroup1":{
        "attributes":[
        {
            "change":false,
            "name":"Name"},
            {
            "change":false,
            "name":"SecondName"},
            ],
        "id":1,
        "name":"MasterTest"},
    "subgroup2":{
        "attributes":[
            {
            "change":true,
            "name":"Name"
            },
            {
            "change":false,
            "name":"Newname"
            }
            ],
        "id":2,
        "name":"MasterSet"},
}}
    

Я пытался использовать команду:

cat test.json | jq '.group[] | select (.attributes[].change==false)

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

Это недопустимый json, и у jq могут возникнуть проблемы с его разбором. Также: каков ожидаемый результат?

Ted Lyngmo 31.12.2022 00:37

Не могу ответить на настоящий вопрос, пока вы не исправите JSON, но в целом cat anything | ... лучше заменить на <anything ...; когда вы даете своей программе настоящий дескриптор файла вместо FIFO, она может делать такие вещи, как распараллеливание ввода-вывода или определение длины файла перед чтением до конца (для информации о ходе выполнения) или пропуск (для гораздо более эффективной реализации такие инструменты, как tail или tac) и т. д.

Charles Duffy 31.12.2022 00:40
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
2
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

.attributes[] перебирает атрибуты, и каждый шаг итерации дает свой собственный результат. Используйте фильтр any, который объединяет несколько значений в одно, в данном случае логическое значение со значением «хотя бы одно»:

.group[] | select(any(.attributes[]; .change==false))
{
  "attributes": [
    {
      "change": false,
      "name": "Name"
    },
    {
      "change": false,
      "name": "SecondName"
    }
  ],
  "id": 1,
  "name": "MasterTest"
}
{
  "attributes": [
    {
      "change": true,
      "name": "Name"
    },
    {
      "change": false,
      "name": "Newname"
    }
  ],
  "id": 2,
  "name": "MasterSet"
}

Демо

Еще один вопрос. Не могли бы вы также посоветовать, как переназначить этот JSON, если я хочу видеть в подгруппе «MasterSet» только атрибуты с «name» = «Newname»?

strmgr 31.12.2022 14:11

@strmgr Затем найдите подгруппу, соответствующую .name == "MasterSet", и map ее массив .attributes, чтобы он содержал только те элементы, которые соответствуют .name == "Newname": … | select(.name == "MasterSet").attributes |= map(select(.name == "Newname"))Демо . Обратите внимание, что это основано буквально на вашем последующем вопросе. Просто показать ранее сопоставленные атрибуты (имеющие .change==false) — это совершенно другой подход (.group[] | .attributes |= map(select(.change==false)) Демо), но он дает тот же результат для этого примера данных.

pmf 31.12.2022 14:37

Большое спасибо еще раз! Мне очень помогает!

strmgr 01.01.2023 17:14

Еще один вопрос - есть ли возможность сортировать печать атрибутов в этом массиве? Бывший. первый "name":"Name" и второй "change":false? Как это сделать также в верхней иерархии ex. первый "MasterSet" и второй "MasterTest"

strmgr 01.01.2023 17:21

Я думаю, что это будет последний вопрос, наконец :)

strmgr 01.01.2023 17:22

Объекты @strmgr JSON не имеют порядка полей, только массивы имеют порядок элементов. Итак, если вы все равно деструктурируете объект, вы можете сначала собрать значения его полей в массив, а затем отсортировать и деструктурировать его. Это можно применить к объекту, удерживаемому .group (вашем внешнему корпусу), который вы деструктурировали с помощью .group[]. Итак, замените .group[] на [.group[]] | sort_by(.name)[], и все готово. Однако с внутренним корпусом это зависит от того, что вы на самом деле имеете в виду (может быть, я просто неправильно понял). Упорядочить элементы массива .attributes просто: поскольку это массив… (1/3)

pmf 01.01.2023 19:29

… просто дополните свой фильтр | .attributes |= sort_by(.name, .change), и он будет отсортирован по критерию, указанному первым, а в случае ничьей — по критерию, заданному вторым. Но если вы хотите видеть упорядоченными сами его элементы, это становится сложной задачей, потому что это объекты, которые, как указано выше, не имеют порядка и, как таковые, просто не могут быть отсортированы должным образом. Конечно, поля отображаются в одном, но это на усмотрение процессора JSON. Любой (другой) процессор, примененный впоследствии, вполне может игнорировать этот порядок. Куда пойти отсюда? Вы можете «пойти на этот риск» и… (2/3)

pmf 01.01.2023 19:29

… заманить процессор jq к созданию определенного порядка, создав новые объекты и предоставив ему поля в выбранном вами порядке. Используйте сопоставление для доступа ко всем элементам массива .attributes, как в | .attributes |= map({name, change}). Другой способ — собрать значения полей в массив, но на этот раз вместе с именами полей отсортировать массив по последним и сохранить значения. Это надежно даст вам порядок, но за счет потери (неупорядоченной) структуры объекта в упорядоченном массиве: | .attributes |= map(to_entries | sort_by(.key) | map(.value)). (3/3)

pmf 01.01.2023 19:29

Мне кажется, что дубликат - это НЕ дубликат, а условие, возникающее из-за вложенной подгруппы, которая создает впечатление дубликата. Вы должны посмотреть, есть ли переключатель для пропуска подгрупп обработки, когда верхний уровень удовлетворяет условию, тем самым избегая предполагаемого дублирования.

Другие вопросы по теме