1 个不稳定版本
0.5.0 | 2023年1月13日 |
---|---|
0.4.1 |
|
0.3.4 |
|
#1387 in 解析器实现
31 每月下载量
120KB
2K SLoC
schema_analysis
类似通用的模式分析
是否曾想过要找出那个json文件中的内容?或者它可能是xml... 嗯,yaml?它肯定不是toml。
然而,许多优秀的工具只能处理其中一种格式,而互联网并不是一个那么友好的地方,以至于最终理解到,不,xml不是一个可接受的文档格式。
现在,这个小巧实用的工具,是我们的朋友serde支持的任何自描述格式的单一接口。
功能
- 与任何具有Serde实现的自我描述格式一起工作。
- 适用于大文件。
- 跟踪每个类型的一些有用信息。
- 分别跟踪null/正常/缺失/重复值。
- 与Schemars和json_typegen集成,如果需要,则生成类型和json模式。
- 这里有一个演示网站这里。
用法
let data: &[u8] = b"true";
// Just pick your format, and deserialize InferredSchema as if it were a normal type.
let inferred: InferredSchema = serde_json::from_slice(data)?;
// let inferred: InferredSchema = serde_yaml::from_slice(data)?;
// let inferred: InferredSchema = serde_cbor::from_slice(data)?;
// let inferred: InferredSchema = toml::from_slice(data)?;
// let inferred: InferredSchema = rawbson::de::from_bytes(data)?;
// let inferred: InferredSchema = quick_xml::de::from_reader(data)?;
// InferredSchema is a wrapper around Schema
let schema: Schema = inferred.schema;
let expected: Schema = Schema::Boolean(Default::default());
assert!(schema.structural_eq(&expected));
// The wrapper is there so we can both do the magic above, and also store the data for later
let serialized_schema: String = serde_json::to_string_pretty(&schema)?;
就是这样。
查看Schema以了解您获得的信息,以及targets以查看可用的集成(包括代码和json模式生成)。
高级用法
我知道,我知道,互联网是邪恶的,它决定用成千上万,甚至数百万的文件来困扰你。
不幸的是,Serde依赖于类型信息来工作,所以我们对此无能为力我们可以拿出重型武器:DeserializeSeed。它拥有您喜欢的Serde的所有特性,但具有运行时状态。
let a_lot_of_json_files: &[&str] = &[ "1", "2", "1000" ];
let mut iter = a_lot_of_json_files.iter();
if let Some(file) = iter.next() {
// We use the first file to generate a new schema to work with.
let mut inferred: InferredSchema = serde_json::from_str(file)?;
// Then we iterate over the rest to expand the schema.
for file in iter {
let mut json_deserializer = serde_json::Deserializer::from_str(file);
// DeserializeSeed is implemented on &mut InferredSchema
// So here it borrows the data mutably and runs it against the deserializer.
let () = inferred.deserialize(&mut json_deserializer)?;
}
// The result in this case would be a simple integer schema
// that 'has met' the numbers 1, 2, and 100.
let mut context: NumberContext<i128> = Default::default();
context.aggregate(&1);
context.aggregate(&2);
context.aggregate(&1000);
assert_eq!(inferred.schema, Schema::Integer(context));
}
此外,如果您需要生成单独的模式(例如在多个线程上运行分析),您可以使用Coalesce特征在事后合并它们。
我真心希望我能将那个Schema转换成一些真正有用的东西。
您很幸运!您可以在这里查看与json_typegen和Schemars的集成,以将分析转换为有用的文件,例如Rust类型和json架构。您还可以在这里找到一个演示网站。
它是如何工作的?
对于更详细的故事,请点击这里,有趣的部分是Serde很体贴地允许格式告诉我们它在处理什么,我们根据这些信息构建一个漂亮的架构。
性能
这些不是正式的基准测试,但应该能给出在一个i7-7700HQ笔记本电脑(2017年)上的大致性能概念,其中原始数据已加载到内存中。
大小 | wasm (MB/s) | 原生 (MB/s) | 格式 | 文件编号 |
---|---|---|---|---|
~180MB | ~20s (9) | ~5s (36) | json | 1 |
~650MB | ~150s (4.3) | ~50s (13) | json | 1 |
~1.7GB | ~470s (3.6) | ~145s (11.7) | json | 1 |
~2.1GB | a | ~182s (11.5) | json | 1 |
~13.3GBb | ~810s (16.4) | xml | ~200k |
a 这个看起来在Web Worker中获取数据时超过了某种浏览器限制,我相信我不得不拆分大文件来处理它。
b ~2.7GB压缩。这看起来可能是一个最坏的情况,因为它包括了解压缩开销,并且文件有一个格式为文本的部分,导致架构非常糟糕。(json格式化的架构接近0.5GB!)
依赖关系
~3–5.5MB
~103K SLoC