#json-schema #generate-json #data #typedef #infer #properties #hint

程序+库 jtd-infer

从示例数据生成 JSON 类型定义模式

3 个不稳定版本

0.2.1 2021年2月1日
0.2.0-test.22021年2月1日
0.1.0 2020年4月26日

#3 in #infer

MIT 许可协议

42KB
698

jtd-infer: 从示例生成 JSON 类型定义模式 Crates.io Docs.rs

JSON 类型定义,又称 RFC8927,是一种易于学习、标准化的方式,用于定义 JSON 数据的模式。您可以使用 JSON 类型定义在不同的编程语言之间可移植地验证数据、创建占位符数据、生成代码等。

jtd-infer 是一个工具,可以从示例数据生成(推断)JSON 类型定义模式。

echo '{ "name": "Joe", "age": 42 }' | jtd-infer | jq
{
  "properties": {
    "age": {
      "type": "uint8"
    },
    "name": {
      "type": "string"
    }
  }
}

安装

在 macOS 上,您可以通过 Homebrew 安装 jtd-infer

brew install jsontypedef/jsontypedef/jtd-infer

对于所有其他平台,您可以从 最新版本 下载并解压二进制文件。您还可以通过运行 cargo 来安装。

cargo install jtd_infer

用法

有关如何使用 jtd-infer 的高级指导,请参阅 JSON 类型定义网站文档中的 "从实际数据推断 JSON 类型定义模式"

基本用法

要调用 jtd-infer,您可以

  1. 让它从 STDIN 读取。这是默认行为。
  2. 让它从一个文件读取。为此,将文件名作为 jtd-infer 的最后一个参数传递。

jtd-infer 读取一个 序列 的 JSON 消息。例如,如果您有一个如下所示的 data.json 文件:

{ "name": "john doe", "age": 42 }
{ "name": "jane doe", "age": 45 }

您可以通过两种方式将其提供给 jtd-infer

# Both of these do the same thing.
cat data.json | jtd-infer
jtd-infer data.json

在这两种情况下,您都会得到这个输出

{"properties":{"name":{"type":"string"},"age":{"type":"uint8"}}}

更改默认数字类型

⚠️ 此部分通常在您将 JSON 类型定义应用到基于 JavaScript 的应用程序时很重要。

默认情况下,JSON 类型定义将推断输入的最具体可能类型。例如,如果您在输入中看到 12,它会猜测 uint8

echo "12" | jtd-infer
{"type":"uint8"}

但是,如果您只向 JSON 类型定义提供了一个小的样本集,或者实际上您有远小于应用程序支持的实际数值数据类型的数据,那么这种行为可能是不希望的。例如,基于 JavaScript 的应用程序通常对所有数值输入都支持 float64,因为 JavaScript 的数字是 IEEE 双精度浮点数。

要告诉 JSON 类型定义使用与其通常猜测不同的类型,您可以使用 --default-number-type 来更改其行为。例如:

# JavaScript numbers are all float64s, and so it's pretty common for JavaScript
# applications to not check if inputs are integers or within a particular range.
#
# If you don't want to make your JSON Typedef schema strict about decimal,
# negative, or out of int range numbers, you can pass float64 as the default
# number type.
echo "12" | jtd-infer --default-number-type=float64
{"type":"float64"}

另一个用例是如果你正在编写一个使用签名字符串32位整数的应用程序,并且你的示例数据实际上从不包含负数或超过8位或16位数字的数字。你可以通过将 int32 作为默认数字类型来实现这一点。

echo "12" | jtd-infer --default-number-type=int32
{"type":"int32"}

请注意,如果 jtd-infer 的默认值与数据不匹配,它将忽略默认值。例如,int32 只与整数一起工作,因此如果出现小数或32位有符号整数无法表示的数字,它将回退到 float64

# both of these output {"type":"float64"}
echo "3.14" | jtd-infer --default-number-type=int32
echo "9999999999" | jtd-infer --default-number-type=int32

高级使用:提供提示

默认情况下,jtd-infer 从不输出 enumvaluesdiscriminator 架构。这是设计决定的:通过始终与其输出保持一致,jtd-infer 更可预测和可靠。

如果你想让 jtd-infer 输出 enumvaluesdiscriminator,你可以使用 --enum-hint--values-hint--discriminator-hint 标志。你可以多次传递这些标志。

所有提示标志都接受 JSON Pointers 作为值。如果你习惯于使用类似于 JavaScript 的语法来引用事物,如 $.foo.bar,则相应的 JSON Pointer 为 /foo/barjtd-infer- 视为“通配符”。 /foo/-/bar 等同于 JavaScript-y 的 $.foo.*.bar

作为一个特殊情况,如果你想指向输入的 / 顶级,那么请使用空字符串作为路径。有关示例,请参阅 "使用 --values-hint"

使用 --enum-hint

默认情况下,字符串总是推断为 { "type": "string" }

echo '["foo", "bar", "baz"]' | jtd-infer
{"elements":{"type":"string"}}

但是,你可以通过提供指向你认为属于枚举的字符串的路径来让 jtd-infer 输出枚举。在这种情况下,它是数组的根元素中的任何元素--相应的 JSON Pointer 为 /-

echo '["foo", "bar", "baz"]' | jtd-infer --enum-hint=/-
{"elements":{"enum":["bar","baz","foo"]}}

使用 --values-hint

默认情况下,对象总是假设为 "struct",并且 jtd-infer 将生成 properties / optionalProperties。例如

echo '{"x": [1, 2, 3], "y": [4, 5, 6], "z": [7, 8, 9]}' | jtd-infer
{"properties":{"y":{"elements":{"type":"uint8"}},"z":{"elements":{"type":"uint8"}},"x":{"elements":{"type":"uint8"}}}}

如果你的数据更像是映射/字典,请传递一个指向你想要获取 values 架构的对象的 values-hint。在这种情况下,它是顶层对象,在 JSON Pointer 中只是一个空字符串

echo '{"x": [1, 2, 3], "y": [4, 5, 6], "z": [7, 8, 9]}' | jtd-infer --values-hint=
{"values":{"elements":{"type":"uint8"}}}

使用 --discriminator-hint

默认情况下,对象总是假设为 "struct",并且 jtd-infer 将生成 properties / optionalProperties。例如

echo '[{"type": "s", "value": "foo"},{"type": "n", "value": 3.14}]' | jtd-infer
{"elements":{"properties":{"value":{},"type":{"type":"string"}}}}

如果你的数据有一个特殊的 "type" 属性,该属性告诉你对象中有什么,那么请使用 --discriminator-hint 来指向该属性。 jtd-infer 将输出适当的 discriminator 架构

echo '[{"type": "s", "value": "foo"},{"type": "n", "value": 3.14}]' | jtd-infer --discriminator-hint=/-/type | jq
{
  "elements": {
    "discriminator": "type",
    "mapping": {
      "s": {
        "properties": {
          "value": {
            "type": "string"
          }
        }
      },
      "n": {
        "properties": {
          "value": {
            "type": "float64"
          }
        }
      }
    }
  }
}

依赖关系

~2.6–4MB
~67K SLoC