顶级对象中的条件无法访问合并的配置

Conditional in the top level object cannot access merged config

我正在处理 jsonnet,我无法访问来自合并对象的 $._config

{
  if ! $._config.hello.enable then {
    'hello': 'world'
  } else {},
} + {
  _config+:: {
    hello: {
      enable: true
    },
  }
}

错误说

unexpected: if while parsing field definition

我不确定为了访问配置参数我可以代表顶层 json 有多么不同

这是语法错误。对象包含字段,而不是表达式。您不能直接将 if 直接放在对象文字中(那甚至意味着什么?)。

不过你也可以这样做:

{
  // Please note, that even if enable = false, the field is still present, but its value is null.
  'hello': if self._config.hello.enable then 'world',
} + {
  _config+:: {
    hello: {
      enable: true
    },
  }
}

$

的含义

我认为 $ 的语义可能有些混乱。它不是指整个文件的结果,而是词法最外层的对象。

例如:

local a = {
  x: "a",
  y: $.x
};
local b = {
  x: "b",
  y: $.x
};
{
  a: a,
  b: b,
} 

结果:

{
  "a": {
    "x": "a",
    "y": "a"
  },
  "b": {
    "x": "b",
    "y": "b"
  }
}

所以基本上就像每次你的代码中有花括号而不在另一对花括号内时它会像那样包裹它 local $ = { ... }; $(模 $ 不是一个通常有效的标识符并且行为与理解略有不同)。

删除/隐藏字段

字段集及其可见性是在创建对象时确定的,因此您不能创建一个字段的存在(或可见性)取决于其他字段的对象。您还可以做一些其他的事情来达到类似的效果,但是 enabled 不能是要创建的对象的一部分或依赖于要创建的对象,因为那将是循环的。

您可以做的一件事是修改对象以隐藏字段,例如:

local enabled = true;
{hello: "world"} + 
(if enabled then {} else {hello:: super.hello})

或者,您也可以根据对象之外的某些其他值使字段的存在成为条件:

local enabled = true; { [if enabled then "hello"]: "world" }

请注意,在这种情况下,该字段将根本不存在 – 这与仅隐藏它不同。当它被隐藏时,它不会被打印出来,对等式检查等无关紧要,但它仍然存在。如果它不存在,那么好吧,它根本不存在。

一个特例是将您的对象包装在一个函数中,该函数采用配置而不是将其作为对象的一部分。

local makeMyObject(config) = {
  [if config.enabled then "hello"]: 
}

另一种方法是拥有一个包含目标对象和配置的包装器对象:

local wrapper = {
  myObject: {
    // Note that self in field name expressions refers to the outer object (wrapper)
    // This makes sense, because they're evaluated before myObject is created.  
    [if self.config.enabled then "hello"]: "world",
  },
  config: {
    enabled: true
  }
}; wrapper.myObject