2个版本
0.1.1 | 2020年9月8日 |
---|---|
0.1.0 | 2020年9月8日 |
#2272 in 解析实现
61KB
2K SLoC
Transporter
用于安全、跨语言API类型的代码生成器
设置
- 确保
~/.cargo/bin
已添加到您的PATH
中(运行export PATH="$PATH:$HOME/.cargo/bin
) cargo安装 transporter
工作原理
Transporter 是一个命令行工具,它生成可以轻松序列化和反序列化(主要是对/从 JSON)的数据结构,以便在不同的语言之间通过 http(s) 传输。
为什么不使用 GraphQL?
因为您想避免完全从头开始重新思考您的 API。与 GraphQL 相比,Transporter 不是一个查询语言。它所做的只是添加传输类型安全。
为什么不使用 Protocol Buffers?
因为 Protocol Buffers 以超级空间高效的二进制格式传输。Transporter 生成的类型以 JSON 格式传输,您可以像读取和调试任何其他基于 JSON 的 API 一样读取和调试它。
为什么不使用 OpenAPI?
因为它不支持通配符路径(可变数量的路径参数)。
为什么不使用 JSON Schema?
因为有大量不同版本的规范,工具大多过时,并且没有优雅的方式映射标签联合。
特性
Transporter 读取 toml 文件作为输入,其中类型是用以下术语定义的:
基本类型
- 字符串
- 整数
- 浮点数
- 布尔值
由于 Transporter 类型通常不可为空,因此可空类型必须定义为
- 可选(表示为
(string)
)
对于其他结构化数据,也存在
集合类型
- 列表(
[string]
),序列化为 JSON 数组 - 字典(
{string}
),序列化为 JSON 对象
用户定义的类型可以是
别名
[ alias.Addressbook ]
type = "[Contact]"
在这个例子中,别名 "Addressbook" 被赋予联系人列表。
结构
[ struct.PhoneNumber ]
type = "PhoneNumberType"
number = "string"
[ struct.Contact ]
name = "string"
phone = "[PhoneNumber]"
在这个例子中定义了两个结构
PhoneNumber
包含两个字段,type
和number
Contact
也包含两个字段,name
和phone
结构体序列化为 JSON 对象({"name":"John Doe","phone":[...]}
)
标签联合
[ union.PhoneNumberType ]
Mobile = {}
Home = {}
Custom = { name = "string" }
在这个例子中定义了一个联合类型。Transporter 中的联合类型通常是标签联合。一个 PhoneNumberType::Mobile
的实例将被序列化为仅仅是 "Mobile"
。一个设置为 "Work"
的 PhoneNumberType::Custom
的实例将被序列化为 {"Custom":{"name":"Work"}}
。
语言支持
目前,Transporter 支持 Rust 和 PHP。在未来不久,计划支持 Elm 和 TypeScript / Javascript。
Rust
在 Rust 中,上述示例大致翻译为(省略了一些 serde 宏)
type Addressbook = Vec<Contact>;
struct PhoneNumber {
type_: PhoneNumberType,
number: String,
}
struct Contact {
name: String,
phone: Vec<PhoneNumber>,
}
enum PhoneNumberType {
Mobile,
Home,
Custom {
name: String,
},
}
PHP
在 PHP 中,上述示例将翻译为类,例如
// Addressbook.php
class Addressbook {
private $value;
public function __construct(array $value) {...}
public function get() : array {...}
public function set(array $value) {...}
public function deserialize($input) : Self {...}
}
// PhoneNumber.php
class PhoneNumber {
private $type;
private $number;
public function __construct(array $fields) {...}
public function getType() : PhoneNumberType {...}
public function setType(PhoneNumberType $value) {...}
public function getNumber() : string {...}
public function setNumber(string $value) {...}
...
}
// Contact.php
class Contact {...}
// PhoneNumberType.php
abstract class PhoneNumberType {...}
// PhoneNumberType/Mobile.php
class Mobile extends PhoneNumberType {...}
// PhoneNumberType/Home.php
class Home extends PhoneNumberType {...}
// PhoneNumberType/Custom.php
class Custom extends PhoneNumberType {...}
依赖项
~2–2.8MB
~45K SLoC