LINUX.ORG.RU

Сортировка JSON 18+

 , , , ,


0

2

Есть JSON-файл file1 с таким содержимым:

{
  "girls": {
    "0": {"name": "Маша", "position": 555},
    "1": {"name": "Анка", "position": 777},
    "2": {"name": "Ната", "position": 888}
  }
}
Подскажите как отсортировать girls по значению name и установить их position равным позиции в безымянном отсортированном списке (+1?) ?
Должно получится:
{
  "girls": {
    "0": {"name": "Анка", "position": 1},
    "1": {"name": "Маша", "position": 2},
    "2": {"name": "Ната", "position": 3}
  }
}
В man jq глядел и не понял.
Поделитесь правильными примерами на скриптовых языках, кто умеет.

★★★★★

Последнее исправление: superuser (всего исправлений: 11)

Ответ на: комментарий от theNamelessOne

Не пейшу я давно на скриповых давно, что знал - всё забыл.
Пример на jq хочу.

superuser ★★★★★
() автор топика

Мимопроходил, а почему индексы ключами, а не просто:

{
  "girls": [
    {"name": "Анка", "position": 1},
    {"name": "Маша", "position": 2},
    {"name": "Ната", "position": 3}
  ]
}
vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

Хочу отсортировать закладки в расширении для chrome. Структура там сложнее и не я пейсал её. Так надо в общем.

superuser ★★★★★
() автор топика
Последнее исправление: superuser (всего исправлений: 1)
Ответ на: комментарий от superuser

В jq есть сортировка, счетчики и возможность модифицировать ключи и значения. Но как это сложить вместе для твоего случая — пока не знаю; поковыряю, как доберусь до компьютера.

ЗЫ я бы лучше питоном такое решал.

filosofia
()
Ответ на: комментарий от filosofia

Меня вообще смущает этот список безымянных элементов 0 1 2. Как его в пути до поля сортировки указывать не пойму.

superuser ★★★★★
() автор топика
Ответ на: комментарий от no-such-file

Ну дай пример, пусть тут будет

superuser ★★★★★
() автор топика
Ответ на: комментарий от NeXTSTEP
$ jq "[.girls[]] | sort_by(.name) | with_entries(. as $a | {key:.key | tostring, value:(.value | .position=$a.key+1)})" file1
jq: error: syntax error, unexpected '|', expecting '$' or '[' or '{' (Unix shell quoting issues?) at <top-level>, line 1:
[.girls[]] | sort_by(.name) | with_entries(. as  | {key:.key | tostring, value:(.value | .position=.key+1)})                                                 
jq: 1 compile error

А... кавычки надо одинарные.
Спасибо, работает.

superuser ★★★★★
() автор топика
Последнее исправление: superuser (всего исправлений: 1)

Не нужно тебе jq, особенно, если структура еще сложнее.

var obj = {
  "girls": {
    "0": {"name": "Маша", "position": 555},
    "1": {"name": "Анка", "position": 777},
    "2": {"name": "Ната", "position": 888}
  }
}
obj.girls = Object.values(obj.girls).sort((a,b)=>a.name < b.name ? -1 : 1);
obj.girls.forEach((v,i)=>v.position = i + 1);
obj.girls = obj.girls.reduce((a, b, i) => (a[i] = b, a), {});

И получаешь свою структуру говна назад.
{
  girls: {
    '0': { name: 'Анка', position: 1 },
    '1': { name: 'Маша', position: 2 },
    '2': { name: 'Ната', position: 3 }
  }
}
Проще и понятнее, чем эти ваши заклинания на jq.

crutch_master ★★★★★
()
.girls |= (
          to_entries
        | sort_by(.value.name)
        | (
                  [., [range(length)]]
                | transpose
                | map(.[0].value.position = .[1] | .[0])
        )
        | from_entries
)

Если нужно от единицы, то range(1; length + 1).

Наслаждайся.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)

По стандарту, поля в json-е не обязаны сохранять порядок, потому то, что ты хочешь, не имеет смысла, либо говорит о том, что у тебя данные смоделированы неправильно. Тебе нужен массив.

nikolnik ★★★
()
Ответ на: комментарий от nikolnik

Тебе нужен массив.

У него там хром на другом конце, который как раз таки производит зачем-то всё это непотребство.

crutch_master ★★★★★
()
Ответ на: комментарий от intelfx

ты тупо полагаешься на ключи в исходном словаре

А? Они отбрасываются же.

$ jq -c "[.girls[]]" < input.json
[{"name":"Анка","position":777},{"name":"Маша","position":555},{"name":"Ната","position":888}]

Но это же совсем не то

Ты бы сравнил для начала результат моего запроса, своего, и примера из оп-поста.

NeXTSTEP ★★
()
Последнее исправление: NeXTSTEP (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Да все равно фигня какая-то, не верю, автор что-то просто не так делает

nikolnik ★★★
()
Ответ на: комментарий от intelfx

Работает отлично, вообще без допиливания (girls на groups только поменял). Буду изучать. Спасибо.

superuser ★★★★★
() автор топика
Последнее исправление: superuser (всего исправлений: 1)

Попробуй JsonLogic, он как раз для манипуляций с JSON и предназначен. Его можно рассматривать как аналог XSLT из мира XML.

hummer
()
Ответ на: комментарий от superuser

Если структура сложнее, то тебе определенно нужен язык, а не jq

Aswed ★★★★★
()
Ответ на: комментарий от superuser

Возми питон или javascript там из коробки есть json поддержка. А в прочем в любом актуальном скриптовом языке из коробки есть json

Aswed ★★★★★
()
Ответ на: комментарий от nikolnik

По стандарту, поля в json-е не обязаны сохранять порядок

забавно, что по стандарту JSON не обязаны, а по стандарту JavaScript обязаны. )

drsm ★★
()
Ответ на: комментарий от superuser

A на Python -е никто не напишет правильный пример?

Правильный не правильный, но рабочий однострочник:

import ujson
import pprint
from functools import reduce


data = """
{
  "girls": {
    "0": {"name": "Маша", "position": 555},
    "1": {"name": "Анка", "position": 777},
    "2": {"name": "Ната", "position": 888}
  }
}
"""


d = ujson.loads(data)
d['girls'] = reduce(
    lambda a, c: {**a, **{c[0]: {**c[1], **{'position': c[0] + 1}}}},
    enumerate(sorted(d['girls'].values(), key=lambda x: x['name'])), {})

pprint.pprint(d)
{'girls': {0: {'name': 'Анка', 'position': 1},
           1: {'name': 'Маша', 'position': 2},
           2: {'name': 'Ната', 'position': 3}}}
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Или, если устроят ключи не текстовые и нужна только сортировка, то ещё проще:

d['girls'] = dict(enumerate(sorted(d['girls'].values(), key=lambda x: x['name'])))
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)

Оформил, сойдёт. Гусары, продолжайте!

superuser ★★★★★
() автор топика

Порядок свойств в объекте вроде бы не определен. Делай из них массив и сортируй на лету.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Порядок свойств в объекте вроде бы не определен.

разумеется, зачем его определять

superuser ★★★★★
() автор топика
Ответ на: комментарий от drsm

in ascending chronological order of property creation

А создавать js объект из текста в правильном для тебя порядке никто не обязан.

тут еще можешь почитать https://github.com/nginx/njs/issues/189

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

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от crutch_master

А создавать js объект из текста в правильном для тебя порядке никто не обязан.

нет, обязан. поля у js объекта имеют упоротый, но тем не менее well defined order:

> JSON.stringify(JSON.parse('{"a":1,"b":2,"c":3,"3":4,"5":6}'))
'{"3":4,"5":6,"a":1,"b":2,"c":3}'

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

я c этим и не спорил.

другое дело, что фича эта была введена для обеспечения совместимости говнокода между браузерами, а теперь форсится как солюшен на который можно положиться, что делает interop с каким-нибудь Go довольно веселым.

drsm ★★
()
Последнее исправление: drsm (всего исправлений: 1)
Ответ на: комментарий от drsm

нет, обязан.

Ну я сделаю свой мегапарсер и все поля у тебя будут с него через жопу.

а теперь форсится как солюшен на который можно положиться

Таким форсерам надо в стенку головой форситься.

crutch_master ★★★★★
()
Ответ на: комментарий от superuser

Хочу отсортировать закладки в расширении для chrome. Структура там сложнее и не я пейсал её. Так надо в общем.

https://chrome.google.com/webstore/detail/speed-dial-2-new-tab/jpfpebmajhhope...

Сортировка групп по алфавиту:

$ sqlite3 ${HOME}/.config/chromium/Default/databases/chrome-extension_jpfpebmajhhopeonhlcgidhclcccjcik_0/1 "update groups set position=(select xxx from (select 1 + row_number() over (order by title) as xxx, id as idxxx from groups) where idxxx=id);"

Это в честь Релиз SQLite 3.36.0

superuser ★★★★★
() автор топика
Последнее исправление: superuser (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.