【问题标题】:Deriving the list of JSON Paths from a JSON Schema model从 JSON Schema 模型派生 JSON 路径列表
【发布时间】:2019-01-14 10:34:47
【问题描述】:

我正在寻找一个 Javascript 库来列出基于 Json Schema 的可能 Json 路径。

对于像下面这样的 json 架构,我想列出可能的 json 路径。

{
  "$id": "https://example.com/person.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Customer",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "description": "The person's first name."
    },
    "lastName": {
      "type": "string",
      "description": "The person's last name."
    },
    "age": {
      "description": "Age in years which must be equal to or greater than zero.",
      "type": "integer",
      "minimum": 0
    },
    "address": {
        "type": "object",
        "city": {
            "type": "string",
        },
        "country": {
            "type": "string",
        }
    }
  }
}

可能的 Json 路径:firstName、lastName、age、address.city 和 address.country

【问题讨论】:

  • 我认为您的架构无效。 address 的架构应该有一个 properties 关键字,其中包含 citycountry

标签: javascript json jsonschema jsonpath


【解决方案1】:

您不一定需要一个库。你可以使用一个简单的递归函数:

var schema = {
  "$id": "https://example.com/person.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Customer",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "description": "The person's first name."
    },
    "lastName": {
      "type": "string",
      "description": "The person's last name."
    },
    "age": {
      "description": "Age in years which must be equal to or greater than zero.",
      "type": "integer",
      "minimum": 0
    },
    "address": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
        },
        "country": {
          "type": "string",
        }
      }
    }
  }
};

var path = ({properties}) =>
  Object.keys(properties).reduce((acc, key) =>
    acc.concat(properties[key].type !== 'object' ? key :
      path(properties[key]).map(p => `${key}.${p}`)), []);

console.log(

  path(schema)

);

【讨论】:

    【解决方案2】:

    基于@customcommander 的回答

    • 添加对 $ref 的支持(防止递归)
    • 也添加层次结构父路径(即 a.b.c -> a + a.b + a.b.c)
    • 添加对数组项的支持(使用 [] 作为通用索引器)

    const _derivePathsFromSchema = (schema, properties, defined) => {
      let paths = [];
      if (!properties) return paths;
      return Object.keys(properties).reduce((paths, childKey) => {
        let child = properties[childKey];
        const { $ref, ...childProperties } = child;
        if ($ref?.startsWith('#/definitions/')) {
          const definition = $ref.substr($ref.lastIndexOf('/') + 1);
          if (!defined.includes(definition)) // prevent recursion of definitions
          {
            defined.push(definition);
            child = {
              ...schema.definitions[definition], // load $ref properties
              ...childProperties, // child properties override those of the $ref
            };
          }
        }
        if (child.type === 'object') {
          return paths.concat(childKey, _derivePathsFromSchema(schema, child.properties, defined.slice()).map(p => `${childKey}.${p}`));
        }
        if (child.type === 'array' && child.items?.properties) {
          return paths.concat(childKey, `${childKey}[]`, _derivePathsFromSchema(schema, child.items.properties, defined.slice()).map(p => `${childKey}[].${p}`));
        }
    
        return paths.concat(childKey);
      }, paths);
    };
    const derivePathsFromSchema = schema => _derivePathsFromSchema(schema, schema.properties, []);
    
    
    console.log(derivePathsFromSchema({
      "$schema": "http://json-schema.org/draft-07/schema#",
      "definitions": {
        "BType": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/definitions/AType"
            }
          }
        },
        "AType": {
          "type": "object",
          "properties": {
            "b": {
              "$ref": "#/definitions/BType"
            }    
          }
        }
      },
      "type": "object",
      "properties": {
        "a": {
          "$ref": "#/definitions/AType"
        },
        "b": {
          "$ref": "#/definitions/BType"
        },
        "id": {
          "type": "string"
        },
        "array": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "item": { "type": "string" }
            }
          }
        },
        "obj": {
          "type": "object",
          "properties": {
            "nested": { "type": "string" }
          }
        }
      }
    }));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-07
      • 1970-01-01
      相关资源
      最近更新 更多