从 JSON 模式模型派生 JSON 路径列表

Man*_*ani 5 javascript json jsonschema jsonpath

我正在寻找一个 Javascript 库来列出基于 Json 架构的可能的 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",
        }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Eli*_*rer 5

基于@customcommander的回答

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

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" }
      }
    }
  }
}));
Run Code Online (Sandbox Code Playgroud)


cus*_*der 3

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

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)

);
Run Code Online (Sandbox Code Playgroud)