Jsonnet的 std.mergePatch
实施 RFC7396但在我的天真测试中,我并没有发现它的行为方式与 +
操作员;例如 +
经营者尊重 x+
句法。std.mergePatch
是 在Jsonnet中实现 本身,这似乎暗示着它与。+
操作符,我想这是一个内置的。
这两种合并方式的语义有什么不同?
Jsonnet的 +
和 std.mergePatch
是完全不同的操作。的 +
操作者只在一个层面上操作,并且 std.mergePatch
递归地遍历对象并合并嵌套对象。用一个例子来解释是最简单的。
local foo = { a: {b1: {c1: 42}}},
bar = { a: {b2: {c2: 2}}};
foo + bar
输出。
{
"a": {
"b2": {
"c2": 2
}
}
}
请注意 bar.a
彻底取代 foo.a
. 随着 +
第二个对象中的所有字段覆盖第一个对象中的字段。比较一下使用 std.mergePatch(foo, bar)
.
{
"a": {
"b1": {
"c1": 42
},
"b2": {
"c2": 2
}
}
}
由于两个 foo
和 bar
有田 a
,是合并的,最后的结果中包含了 b1
和 b2
.
所以重申一下: +
是一个 "平坦 "的操作,用第二个对象的字段覆盖第一个对象的字段。
但这还不是故事的结尾。你提到了 field+: value
语法,我将尝试解释它的真正作用。在Jsonnet中 +
不仅仅是覆盖,而是OO意义上的继承。它创建的对象是第二个对象继承第一个对象的结果。有一个这样的操作符有点异国情调--在所有主流语言中,这样的关系都是静态定义的。在Jsonnet中,当你做 foo + bar
జజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ bar
对象可以访问来自 foo
通过 super
:
{ a: 2 } + { a_plus_1: super.a + 1}
这样做的结果是:
{
"a": 2,
"a_plus_1": 3
}
你可以使用这个功能来合并更深层次的领域。
{ a: {b: {c1: 1}, d: 1}} +
{ a: super.a + {b: {c2: 2} } }
结果是:
{
"a": {
"b": {
"c2": 2
},
"d": 1
}
}
不过这有点重复(如果字段名再长一点就会很烦)。所以我们有一个很好的语法糖来解决这个问题。
{ a: {b: {c1: 1} , d: 1}} +
{ a+: {b: {c2: 2}} }
请注意,在这些例子中,我们只对我们选择的一个特定字段进行了合并。我们仍然替换了 a.b
. 这就灵活多了,因为在很多情况下,你不能天真地把里面所有的东西都合并起来(有时一个嵌套对象是 "原子 "的,应该完全替换)。
中的版本是 +:
的工作方式与带 super
. 微妙的区别在于 +:
实际上翻译成这样 if field in super then super.field + val else val
的时候,也会返回相同的值。super
完全没有提供或没有这个特定的字段。例如 {a +: {b: 42}}
评价为 {a: { b: 42 }}
.
强制布道:而 +
是非常强大的,请不要滥用它。当你需要给某些东西设置参数时,可以考虑使用函数而不是继承。