Jsonnet中的+操作符和std.mergePatch有什么区别?

问题描述 投票:0回答:1

Jsonnet的 std.mergePatch 实施 RFC7396但在我的天真测试中,我并没有发现它的行为方式与 + 操作员;例如 + 经营者尊重 x+ 句法。std.mergePatch在Jsonnet中实现 本身,这似乎暗示着它与。+ 操作符,我想这是一个内置的。

这两种合并方式的语义有什么不同?

merge operators jsonnet
1个回答
4
投票

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
      }
   }
}

由于两个 foobar 有田 a,是合并的,最后的结果中包含了 b1b2.

所以重申一下: + 是一个 "平坦 "的操作,用第二个对象的字段覆盖第一个对象的字段。

但这还不是故事的结尾。你提到了 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 }}.

强制布道:而 + 是非常强大的,请不要滥用它。当你需要给某些东西设置参数时,可以考虑使用函数而不是继承。

© www.soinside.com 2019 - 2024. All rights reserved.