从可JSON化的结构生成用于反序列化对象图的代码。
项目描述
Mapry从可JSON化的结构生成用于反序列化对象图的代码。
故事。我们需要另一种领域特定的语言用于内部数据交换和系统配置。现有的解决方案大多集中在将配置建模为没有对象间 交叉引用 的层次结构的 对象树。
例如,将对象树想象成JSON对象或数组。我们发现这种结构对于大多数复杂消息和系统配置来说非常有限。我们的用例要求数据中的对象相互引用 - 我们需要的不是对象树,而是 对象图。
此外,我们希望序列化本身是 可读的,以便操作员可以使用简单的文本编辑器对其进行编辑。可JSON化结构与许多现有工具(如JSON和YAML模块)很好地匹配。
然而,JSON只允许有限的数据类型(数字、字符串、数组和对象/映射)。我们发现我们的大部分数据依赖于比标准JSON提供的更丰富的原始数据集。这个扩展集包括
日期,
日期时间,
一天中的时间,
时区,
持续时间,以及
路径。
虽然存在针对对象树的多种语言序列化器(例如,例如,协议缓冲区)、针对对象图的特定语言序列化器(例如,例如 Go 中的Gob或Python中的Pickle)或具有有限原始数据集的多语言序列化器(例如,例如 Flatbuffers),但据我们所知,目前还没有能够在多个语言中一致提供可读表示和丰富原始数据集的对象图序列化器。
因此,我们开发了Mapry,它可以从可序列化为JSON的结构生成对象图的多语言反序列化代码。
对象图的模式存储在单独的JSON文件中,并定义了对象图中使用的所有数据类型,包括对象图本身。代码基于该模式生成。您只需定义一次模式,然后就可以自动生成所有支持语言的代码。模式可以演进,并通过可选属性支持向后兼容。
支持的语言
目前,Mapry实现了以下语言绑定
C++11,
Go 1和
Python 3。
由于序列化需要在不同的语言中操作,因此仅支持语言功能的交集。例如,由于Go不支持继承或联合类型,因此Mapry也不支持它们。
工作流程
以下图表说明了工作流程。
文档
本文档仅提供了Mapry的简要概述。完整的文档可以在这里找到。
介绍
在这里,我们将通过展示一个简短的示例来介绍Mapry,以便您对生成器的使用有一个初步印象。要全面了解,请查阅文档。
模式以名称和描述开始,接着是特定语言的设置(指定代码生成的非标准部分),然后是图结构的定义,最后是对象图本身的属性定义。
以下是一个示例模式,以供您了解
{
"name": "Pipeline",
"description": "defines an address book.",
"cpp": {
"namespace": "book::address",
"path_as": "boost::filesystem::path",
"optional_as": "std::experimental::optional",
"datetime_library": "ctime"
},
"go": {
"package": "address"
},
"py": {
"module_name": "book.address",
"path_as": "pathlib.Path",
"timezone_as": "pytz.timezone"
},
"classes": [
{
"name": "Person",
"description": "defines a contactable person.",
"properties": {
"full_name": {
"type": "string",
"description": "gives the full name (including middle names)."
},
"birthday": {
"type": "date",
"description": "indicates the birthday in UTC."
},
"address": {
"type": "Address",
"description": "notes where the person lives."
}
}
}
],
"embeds": [
{
"name": "Address",
"description": "defines an address.",
"properties": {
"text": {
"type": "string",
"description": "gives the full address."
}
}
}
],
"properties": {
"maintainer": {
"type": "Person",
"description": "indicates the maintainer of the address book."
}
}
}
一旦您使用Mapry生成了反序列化代码,您就可以使用它从可序列化为JSON的结构中获取对象图。
例如,假设一个可序列化为JSON的结构存储在/path/to/the/file.json
{
"persons": {
"alice": {
"full_name": "Alice Doe",
"birthday": "1983-10-24",
"address": {
"text": "Some street 12, Some City, Some Country"
}
},
"bob": {
"full_name": "Bob Johnson",
"birthday": "2016-07-03",
"address": {
"text": "Another street 36, Another City, Another Country"
}
}
},
"maintainer": "alice"
}
您可以使用Python解析对象图
# Obtain a JSONable
pth = '/path/to/the/file.json'
with open(pth, 'rt') as fid:
value = json.load(fid)
# Parse the JSONable
errors = book.address.parse.Errors(cap=10)
pipeline = book.address.fromjsonable.pipeline_from(
value=value,
ref=pth + '#',
errors=errors)
if not errors.empty():
for error in errors.values():
print("{}: {}".format(error.ref, error.message), file=sys.stderr)
return 1
并将对象图作为pipeline访问
print('Persons are:')
for person in pipeline.persons:
print('{} (full name: {}, address: {}, birthday: {})'.format(
person.id,
person.full_name,
person.address.text,
person.birthday.strftime("%d.%m.%Y")))
print('The maintainer is: {}'.format(
pipeline.maintainer.id))
用法
Mapry通过mapry-to命令提供单一入口点进行所有代码生成。
要生成不同语言的代码,请调用
对于**C++**
mapry-to cpp \
--schema /path/to/schema.json \
--outdir /path/to/cpp/code
对于**Go**
mapry-to go \
--schema /path/to/schema.json \
--outdir /path/to/go/code
对于**Python**
mapry-to py \
--schema /path/to/schema.json \
--outdir /path/to/py/code
如果输出目录不存在,它将被创建。任何现有的文件都将被静默覆盖。
安装
我们提供可预包装的PEX文件,可以轻松下载和执行。请参阅发布部分。
如果您希望将 Mapry 作为库(例如,作为您基于 Python 的构建系统的一部分)来使用,请使用 pip 进行安装
pip3 install mapry
贡献
所有贡献都备受欢迎。请参阅文档中的此页面,了解您如何进行贡献:贡献页面。
版本控制
我们遵循 语义版本控制。我们扩展了标准的语义版本控制,添加了一个额外的格式版本。版本 W.X.Y.Z 表示
W 是格式版本(数据表示向后不兼容),
X 是主要版本(库接口向后不兼容),
Y 是次要版本(库接口扩展,但向后兼容),
Z 是补丁版本(向后兼容的错误修复)。
项目详情
mapry-1.0.0.4.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6f6ae29ab8d821985a1c099dbae9986ad20828e48c9a604d1f88d13d7a91f2c6 |
|
MD5 | 80b0fa64a67463287960bf90cccc514c |
|
BLAKE2b-256 | 359aec44d01133591250a0d9c987f94d9c7b86005a5024738d2af740e83da30e |