Schwierigkeiten beim Aufbau einer verschachtelten Datenstruktur


14

Beim Versuch, eine JSON-Nachricht für eine API zu erstellen, hatte ich Schwierigkeiten, etwas zu tun, von dem ich dachte, dass es einfach wäre. Ich musste eine Nachricht wie die folgende erstellen:

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

Mein erster Versuch hat jedoch nicht funktioniert:

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

Der Versuch, die Dinge weiter zu vereinfachen, verwirrte mich mehr:

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

Dann habe ich versucht, einige temporäre Variablen zu verwenden, und das hat funktioniert:

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

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

Was ist denn hier los?

Und gibt es eine Möglichkeit, meine gewünschte Ausgabe ohne eine zusätzliche temporäre Variable zu erzielen?


1
say to-json { foo => [ { a => 1 } ] };sollte so etwas ausgeben {"foo":[{"a":1}]}, nicht {"foo":["a":1]}. Letzteres ist ein Tippfehler, oder? Wenn nicht, was say $*PERL.compiler.version;sagt das aus?
Raiph

Hm, ja, du hast recht. Ich glaube, ich habe Dinge falsch verstanden, als ich Sachen ausprobiert habe. Sogar say to-json { foo => [ a => 1 ] }Ausgaben, {"foo":[{"a":1}]}also wer weiß, was ich geschrieben habe, als ich das bekam, wenn ich es jemals getan habe. Mein Fehler!
Jja

Antworten:


17

Sie haben die entdeckt Argument Regel . Zahlreiche Konstrukte in Raku wiederholen das Argument, mit dem sie versehen sind. Dies schließt den [...]Array-Komponisten ein. Deshalb, wenn wir sagen:

say [1..10];

Wir erhalten ein Array, das 10 Elemente enthält, nicht 1. Es bedeutet jedoch auch, dass:

say [[1,2]];

Iteriert das [1,2]und führt somit dazu [1,2]- als ob das innere Array nicht da wäre. A Hashiteriert zu seinen Paaren, also:

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

Produziert tatsächlich:

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

Das heißt, das Array hat die Paare. Der JSON-Serializer serialisiert dann jedes Paar als Ein-Element-Objekt.

Die Lösung besteht darin, ein iterierbares Einzelelement zu erzeugen. Der Infix- ,Operator erzeugt Listen, also können wir das verwenden:

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

Dann ist das einzige Argument, das iteriert werden soll, eine 1-Element-Liste mit einem Hash, und Sie erhalten das gewünschte Ergebnis.

Einfache Möglichkeit, sich daran zu erinnern: Verwenden Sie immer nachgestellte Kommas, wenn Sie die Werte einer Liste, eines Arrays oder eines Hash angeben, auch bei einer Liste mit einzelnen Elementen, es sei denn, Sie geben tatsächlich die einzelne Iterierbarkeit an, aus der sie gefüllt werden soll.


2
Die andere Möglichkeit besteht darin, in einem Skalar aufzulisten: {foo => [$ {a => 1, b => 2}]}
Jakar
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.