"Ternary logic" 返回值:foo、bar 或 error

"Ternary logic" for returned value: foo, bar or error

我有两个不同的 JSON 结构来从中检索特定的对象值,基本上是这样的

{
    "one": {
        "foo": {
            "bar": "baz"
        }
    }
}

还有一个类似的

{
    "two": {
        "foo": {
            "bar": "qux"
        }
    }
}

我想 return 两种情况下的 bar 值加上一个额外的 return 变体 error 以防两种情况 1 - baz - 也不是情况 2 - qux - 匹配任何内容(即匹配 null)。

是否有仅使用 jq 1.6 的简单方法?

更新: 以下是实际 JSON 文件的片段:

/* manifest.json, variant A */
{
    "browser_specific_settings": {
        "gecko": {
            "id": "{95ad7b39-5d3e-1029-7285-9455bcf665c0}",
            "strict_min_version": "68.0"
        }
    }
}

/* manifest.json, variant B */
{
    "applications": {
        "gecko": {
            "id": "j30D-3YFPUvj9u9izFoPSjlNYZfF22xS@foobar",
            "strict_min_version": "53.0"
        }
    }
}

我需要 id 值(*gecko.id 可以这么说)或者 error 如果有 none:

{95ad7b39-5d3e-1029-7285-9455bcf665c0}
j30D-3YFPUvj9u9izFoPSjlNYZfF22xS@foobar
error

我想你正在寻找 hasOwnProperty()

例如:

var value;
if(applications.gecko.hasOwnProperty('id'))
   value = applications.gecko.id;
else
   value = 'error';

您可以组合使用 ? "error suppression" 和 // “替代` 运算符:

jq -n --slurpfile variantA yourFirstFile --slurpfile variantB yourSecondFile \
'(
  ($variantA[0].browser_specific_settings.gecko.id)?, 
  ($variantB[0].applications.gecko.id)?
) // "error"'

这将输出第一个文件的 id and/or 如果两个文件中的任何一个存在,则输出第二个文件的 id,避免在它们不存在时引发错误,而是输出 error如果可以找到 none 个。

如果在您的上下文中有意义,可以将命令缩短如下:

jq -n --slurpfile variantA yourFirstFile --slurpfile variantB yourSecondFile \
'(($variantA[0].browser_specific_settings, $variantB[0].applications) | .gecko.id)? // "error"'

您可以使用下面的过滤器来处理您提供的示例 JSON 内容

jq '.. | if type == "object" and has("id") then .id else empty end'

看他们直播jqplay - VariantA and jqplay - VariantB

注意:这只会在 .id 存在时获取其值,请参阅其他答案()以显示 error当对象不包含必填字段时。

(.. | objects | select(has("id"))).id // "error"

这将适用于多个文件和包含多个独立实体的文件。

jqplay demo

I need the id values (*gecko.id so to speak) or error if there is none:

根据您的记法 "*gecko.id",这里有两个解决方案,第一个将“*”解释为单个未知键(或索引),第二个将其(或多或少)解释为任何数字键或索引:

.[] | .gecko.id // "error"
.. | objects | select(has("gecko")) | (.gecko.id // "error")

如果你不是很在意有没有"gecko"键,你不妨考虑一下:

first(.. | objects | select(has("id")).id ) // "error"