Складність при побудові вкладеної структури даних


14

Намагаючись створити повідомлення JSON для API, я опинився, що намагаюся зробити щось, на що я вважав, що це буде просто. Мені потрібно було створити повідомлення на зразок наступного:

{ "list": [ { "foo": 1, "bar": 2 } ] }

Однак моя перша спроба не вийшла:

say to-json { foo => [ { a => 1, b => 2 } ] };
# {"foo":[{"a":1},{"b":2}]}

Намагання спростити речі ще більше мене збентежило:

say { foo => [ { a => 1 } ] };
# {foo => [a => 1]}
# Note that this is not JSON, but I expected to see curly braces

Потім я спробував використати деякі тимчасові змінні, і це спрацювало:

my @list = { a => 1 };
say to-json { foo => @list };
# {"foo":[{"a":1}]}

my %hash = ( a => 1 );
say to-json { foo => [ %hash ] };
# {"foo":[{"a":1}]}

Що тут відбувається?

І чи є спосіб я досягти бажаного результату без додаткової тимчасової змінної?


1
say to-json { foo => [ { a => 1 } ] };має вивести щось подібне {"foo":[{"a":1}]}, ні {"foo":["a":1]}. Останнє - друкарня, правда? Якщо ні, то що say $*PERL.compiler.version;говорить?
raiph

Гм, так, ти маєш рацію. Напевно, я неправильно читав речі, коли намагався виправити речі. Навіть say to-json { foo => [ a => 1 ] }виходи, {"foo":[{"a":1}]}тож хто знає, що я набрав, коли отримав це, якщо коли-небудь це зробив Моє ліжко!
jja

Відповіді:


17

Ви відкрили єдине правило аргументу . Численні конструкції в Раку повторять аргументи, які їм надаються. Сюди входить [...]композитор масиву. Ось чому, коли ми говоримо:

say [1..10];

Ми отримуємо масив, який містить 10 елементів, а не 1. Однак це також означає, що:

say [[1,2]];

Ітератує [1,2]і, таким чином, призводить до [1,2]- як би внутрішнього масиву там не було. Він Hashповторює свої пари, таким чином:

{ foo => [ { a => 1, b => 2 } ] }

Фактично виробляє:

{ foo => [ a => 1, b => 2 ] }

Тобто масив має пари. Потім серіалізатор JSON серіалізує кожну пару як одноелементний об'єкт.

Рішення полягає у створенні одноелементного ітерабельного. Оператор infix ,- це те, що створює списки, тому ми можемо використовувати це:

say to-json { foo => [ { a => 1, b => 2 }, ] };
#                        note the , here ^

Тоді єдиний аргумент, який слід повторити, - це 1-елементний список із хешем, і ви отримуєте потрібний результат.

Простий спосіб запам’ятати це: завжди використовуйте проміжні коми при вказівці значень списку, масиву чи хешу навіть із одним списком елементів, якщо ви фактично не вказуєте єдиний ітерабел, з якого потрібно заповнити його.


2
Інший спосіб - деталізувати розмір у Скалярі: {foo => [$ {a => 1, b => 2}]}
jakar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.