构造嵌套数据结构时的困难

Difficulty when constructing a nested data structure

在尝试为 API 创建 JSON 消息时,我发现自己很难做一些我认为很简单的事情。我需要创建如下消息:

{ "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}]}

这是怎么回事?

有没有一种方法可以在没有额外临时变量的情况下实现我想要的输出?

您发现了 single argument rule。 Raku 中的许多构造将迭代它们提供的参数。这包括 [...] 数组组合器。这就是为什么当我们说:

say [1..10];

我们得到一个包含 10 个元素而不是 1 个元素的数组。但是,这也意味着:

say [[1,2]];

迭代 [1,2],从而导致 [1,2] - 就好像内部数组不存在一样。 A Hash 迭代到它的对,因此:

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

实际产生:

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

也就是说,数组中有对。 JSON 序列化程序然后将每一对序列化为一个元素对象。

解决方案是生成一个单元素可迭代对象。中缀 , 运算符用于生成列表,因此我们可以使用它:

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

然后要迭代的单个参数是一个带有散列的 1 元素列表,你会得到你想要的结果。

记住它的简单方法:在指定列表、数组或散列的值时始终使用尾随逗号,即使是单个元素列表,除非您实际上是指定要从中填充它的单个可迭代对象。