如何使用正则表达式在任意深度修改JSON属性值?

mec1mxoz  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(171)

我收到了一个JSON模式文件集合,我必须使用它来验证JSON中的一些数据。架构中$ref属性的值不完整。验证程序工具无法解析引用。当我手动编辑某些模式文件中的$ref值时,我可以让验证部分工作。然而,JSON模式文件的集合是巨大的,我不能手动编辑所有这些文件,所以我想我可以使用jq来修复它们。
具有不完整$ref值的模式的示例.

{
  "schema": "http://json-schema.org/draft-04/schema#",
  "id": "FubarAgent",
  "metaFormat": "http://example.org/fubar/",
  "type": "object",
  "properties": {
    "extensions": {
      "$ref": "TypeDefinitions#/extensions"
    },
    "name": {
      "type": "string",
      "maxLength": 2048,
      "title": "name"
    },
    "membership": {
      "oneOf": [
        {
          "$ref": "Membership"
        },
        {
          "type": "string",
          "maxLength": 2048
        }
      ]
    }
  },
  "title": "FubarAgent"
}

问题是每个模式文件都被命名为*object_name*.json。当验证器试图解析名为TypeDefinitionsMembership的文件中的引用时,它会失败,因为这些文件实际上名为TypeDefinitions.jsonMembership.json。上面的引用应该分别是TypeDefinitions.json#/extensionsMembership.json。(所以,不是简单地追加.json。)我试图用jq代码来使用正则表达式在任何深度编辑这些引用,但我还没有完全弄明白。
我在之前的尝试中接近成功,但它在所有深度都不起作用,也没有使用正则表达式。我目前的版本使用正则表达式,并在一些文件上工作,但不是全部。它是...

jq 'walk(if type == "object" and has("$ref") then .["$ref"] = (. | sub("(?<a>[^#]*)(?<b>#.*)*$"; "\(.a).json\(.b + "")")) else . end)' FubarAgent.json

使用上面的示例模式,输出是...

jq: error (at FubarAgent.json:28): object ({"$ref":"Ty...) cannot be matched, as it is not a string

我该怎么做才能修好呢?而且,我拥有的东西似乎很长。也许有一个更短的方法来做到这一点,有人可以推荐?

wi3ka0sx

wi3ka0sx1#

难道你不能更新(|=)每个指向字符串的."$ref"键,通过在第一个#或字符串的末尾加上.json

(.. | objects."$ref" | strings) |= sub("(?<a>#|$)"; ".json\(.a)")
{
  "schema": "http://json-schema.org/draft-04/schema#",
  "id": "FubarAgent",
  "metaFormat": "http://example.org/fubar/",
  "type": "object",
  "properties": {
    "extensions": {
      "$ref": "TypeDefinitions.json#/extensions"
    },
    "name": {
      "type": "string",
      "maxLength": 2048,
      "title": "name"
    },
    "membership": {
      "oneOf": [
        {
          "$ref": "Membership.json"
        },
        {
          "type": "string",
          "maxLength": 2048
        }
      ]
    }
  },
  "title": "FubarAgent"
}

Demo

版本冲突说明:

jq版本1.7修复了一个空正则表达式匹配的bug(参见release info:“修复空正则表达式匹配。@itchyny #2677“)。在此版本之前,$上的组匹配在结果对象中根本不会提供对应的字段(而v1.7生成{"a": ""}),因此.a的字符串插值将计算为null,生成文字字符串"null",在本例中,最终导致"$ref": "Membership.jsonnull"的非预期结果。
对于1.5+版本(因为添加了regexp支持),可以通过显式处理这种情况来缓解:添加// "",以在.a的计算结果为 falsy 值(如null)时手动提供空字符串作为替代。

(.. | objects."$ref" | strings) |= sub("(?<a>#|$)"; ".json\(.a // "")")

相关问题