json jq:默认多个可能不存在的键,在嵌套路径中?

ovfsdjhp  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(118)

我想在jq上设置默认值,并返回根文档。
我所拥有的(注意内部对象中缺少一些属性)如下,但长度不是固定的:

[{"foo":{}},{"foo":{"a":1}},{"foo":{"b":4,"c":23}},{"foo":{"a":15,"b":2,"c":33}}]

字符串
我想要的(默认缺少0的属性):

[
  {
    "foo": {
      "a": 0,
      "b": 0,
      "c": 0
    }
  },
  {
    "foo": {
      "a": 1,
      "b": 0,
      "c": 0,
    }
  },
  {
    "foo": {
      "a": 0,
      "b": 4,
      "c": 23
    }
  },
  {
    "foo": {
      "a": 15,
      "b": 2,
      "c": 33
    }
  }
]


我尝试过类似jq '.[] | (.foo | getpath(["a"]) //= 0)' < in > out的东西,但它返回的是内部对象的流,而不是根文档;这不是我想要的,因为有其他属性来分组记录,我想稍后按它分组。

wqnecbli

wqnecbli1#

如果字段在合并时发生冲突,则右字段将覆盖左字段。您可以通过将默认值放在左侧并与右侧的当前值合并来利用这一事实。对“当前值”的迭代类型取决于您的结构和先决条件。
例如,合并可以是(*)或可以不是(+)深度。以下是两种情况的示例:第一个更新.foo字段,将其与仅包含abc值的对象(浅)合并。第二个更新根对象,方法是将根对象与包含foo.afoo.bfoo.c值的对象(深度)合并。这两种方法都输出原始根级别。

map(.foo |= {a:0, b:0, c:0} + .)

字符串
Demo

map({foo: {a:0, b:0, c:0}} * .)


Demo
或者,如果您想要一种基于路径的方法,您可以提供一个要迭代的路径列表,并根据需要在这些路径上设置值。下面的示例使用了您自己的方法中的替代运算符//(如果计算结果为nullfalse,即使原始值确实存在,也会设置默认值):

map(reduce(
  ["foo", "a"],
  ["foo", "b"],
  ["foo", "c"]
) as $p (.; setpath($p; getpath($p) // 0)))


Demo
您也可以单独提供和设置默认值:

map(reduce(
  [["foo", "a"], 0],
  [["foo", "b"], 0],
  [["foo", "c"], 0]
) as [$p, $v] (.; setpath($p; getpath($p) // $v)))


Demo
在任何情况下,使用map(...)(或.[] |= ...,或[.[] | ...])而不仅仅是.[] | ...,以便处理顶级数组的项并保留数组结构。
给定示例输入,所有这些方法都输出相同的结果(后两个基于路径的示例的字段顺序有所变化,例如↑在某些情况下默认值比原始值“引入得晚”,但它们在逻辑上是等效的):

[
  {
    "foo": {
      "a": 0,
      "b": 0,
      "c": 0
    }
  },
  {
    "foo": {
      "a": 1,
      "b": 0,
      "c": 0
    }
  },
  {
    "foo": {
      "a": 0,
      "b": 4,
      "c": 23
    }
  },
  {
    "foo": {
      "a": 15,
      "b": 2,
      "c": 33
    }
  }
]

oalqel3c

oalqel3c2#

根据我对这个问题的理解,您需要一种简单的方法来生成问题中所示的输出,只需在一个地方设置默认值。这里有一个方法:

def foo(f): {foo: ({a:0, b:0, c:0} + f)};

[
 foo(null),
 foo({a: 1}),
 foo({b: 4, c: 23}),
 foo({a:15,b:2,c:33})
 ]

字符串

相关问题