32 个版本 (20 个破坏性版本)
0.21.1 | 2024 年 7 月 10 日 |
---|---|
0.20.0 | 2024 年 7 月 8 日 |
0.15.1 | 2023 年 12 月 6 日 |
0.15.0 | 2023 年 6 月 6 日 |
0.2.0-alpha | 2020 年 4 月 27 日 |
#56 in 网页编程
6,581 每月下载量
用于 58 个 Crates (7 直接)
2.5MB
24K SLoC
Rust 的 JSON-LD 实现
此包是 JSON-LD 数据交换格式的 Rust 实现。
Linked Data (LD) 是基于标准网页技术建立的 万维网联盟 (W3C) 创新项目,旨在创建一个跨网页的互相关联数据集网络。 JavaScript 对象表示法 (JSON) 是一种广泛使用的简单、非结构化数据序列化格式,用于以可读的方式描述数据对象。JSON-LD 将这两种技术结合在一起,为 JSON 添加语义,创建一种轻量级的数据序列化格式,可以组织数据并帮助网页应用程序在大规模上实现互操作性。
用法
此库的入口点是提供对所有 JSON-LD 转换算法(上下文处理、展开、压缩等)访问的 JsonLdProcessor
特性。如果您想探索和/或转换 ExpandedDocument
,您可能还想查看代表 JSON 对象的 Object
类型。
展开
如果您想展开一个 JSON-LD 文档,首先使用 RemoteDocument
或 RemoteDocumentReference
描述要展开的文档。
RemoteDocument
将文档的 JSON 表示及其远程 URL 封装在一起。RemoteDocumentReference
可以仅表示一个 URL,允许一些加载器通过引用 URL 获取远程文档。
之后,您只需在远程文档上使用 JsonLdProcessor::expand
函数即可。
示例
use iref::IriBuf;
use static_iref::iri;
use json_ld::{JsonLdProcessor, Options, RemoteDocument, syntax::{Value, Parse}};
// Create a "remote" document by parsing a file manually.
let input = RemoteDocument::new(
// We use `IriBuf` as IRI type.
Some(iri!("https://example.com/sample.jsonld").to_owned()),
// Optional content type.
Some("application/ld+json".parse().unwrap()),
// Parse the file.
Value::parse_str(r#"
{
"@context": {
"name": "http://xmlns.com/foaf/0.1/name"
},
"@id": "https://www.rust-lang.net.cn",
"name": "Rust Programming Language"
}"#).expect("unable to parse file").0
);
// Use `NoLoader` as we won't need to load any remote document.
let mut loader = json_ld::NoLoader;
// Expand the "remote" document.
let expanded = input
.expand(&mut loader)
.await
.expect("expansion failed");
for object in expanded {
if let Some(id) = object.id() {
let name = object.as_node().unwrap()
.get_any(&iri!("http://xmlns.com/foaf/0.1/name")).unwrap()
.as_str().unwrap();
println!("id: {id}");
println!("name: {name}");
}
}
以下是一个使用 RemoteDocumentReference
的示例。
use static_iref::iri;
use json_ld::{JsonLdProcessor, Options, RemoteDocumentReference};
let input = RemoteDocumentReference::iri(iri!("https://example.com/sample.jsonld").to_owned());
// Use `FsLoader` to redirect any URL starting with `https://example.com/` to
// the local `example` directory. No HTTP query.
let mut loader = json_ld::FsLoader::default();
loader.mount(iri!("https://example.com/").to_owned(), "examples");
let expanded = input.expand(&mut loader)
.await
.expect("expansion failed");
最后,将相同的例子中的 IriBuf
替换为轻量级的 rdf_types::vocabulary::Index
类型。
use rdf_types::{Subject, vocabulary::{IriVocabularyMut, IndexVocabulary}};
use contextual::WithContext;
// Creates the vocabulary that will map each `rdf_types::vocabulary::Index`
// to an actual `IriBuf`.
let mut vocabulary: IndexVocabulary = IndexVocabulary::new();
let iri_index = vocabulary.insert(iri!("https://example.com/sample.jsonld"));
let input = RemoteDocumentReference::iri(iri_index);
// Use `FsLoader` to redirect any URL starting with `https://example.com/` to
// the local `example` directory. No HTTP query.
let mut loader = json_ld::FsLoader::default();
loader.mount(iri!("https://example.com/").to_owned(), "examples");
let expanded = input
.expand_with(&mut vocabulary, &mut loader)
.await
.expect("expansion failed");
// `foaf:name` property identifier.
let name_id = Subject::Iri(vocabulary.insert(iri!("http://xmlns.com/foaf/0.1/name")));
for object in expanded {
if let Some(id) = object.id() {
let name = object.as_node().unwrap()
.get_any(&name_id).unwrap()
.as_value().unwrap()
.as_str().unwrap();
println!("id: {}", id.with(&vocabulary));
println!("name: {name}");
}
}
压缩
JSON-LD 压缩是一种转换,通过应用上下文到给定的 JSON-LD 文档中来减小其大小。根据您的起点,使用此库有两种方式来获取压缩的 JSON-LD 文档
- 如果您想获取任意远程文档的压缩表示形式,只需使用
JsonLdProcessor::compact
(或JsonLdProcessor::compact_with
)方法。 - 否则,要压缩
ExpandedDocument
,您可以使用Compact::compact
方法。
示例
以下是一个使用 JsonLdProcessor::compact
对任意 RemoteDocumentReference
进行压缩的示例。
use static_iref::iri;
use json_ld::{JsonLdProcessor, Options, RemoteDocumentReference, RemoteContextReference, syntax::Print};
let input = RemoteDocumentReference::iri(iri!("https://example.com/sample.jsonld").to_owned());
let context = RemoteContextReference::iri(iri!("https://example.com/context.jsonld").to_owned());
// Use `FsLoader` to redirect any URL starting with `https://example.com/` to
// the local `example` directory. No HTTP query.
let mut loader = json_ld::FsLoader::default();
loader.mount(iri!("https://example.com/").to_owned(), "examples");
let compact = input
.compact(context, &mut loader)
.await
.expect("compaction failed");
println!("output: {}", compact.pretty_print());
展平
JSON-LD 展平是一种转换,其目的是将嵌套节点移出。结果是文档中声明的所有节点的列表。根据您的起点,使用此库有两种方式来展平 JSON-LD 文档
- 如果您想获取任意远程文档的压缩表示形式,只需使用
JsonLdProcessor::flatten
(或JsonLdProcessor::flatten_with
)方法。这将返回一个 JSON-LD 文档。 - 否则,要展平
ExpandedDocument
,您可以使用Flatten::flatten
(或Flatten::flatten_with
)方法。这将返回节点列表作为FlattenedDocument
。
展平需要为嵌套匿名节点分配一个标识符,这就是为什么展平函数需要一个 rdf_types::MetaGenerator
作为参数。这个生成器负责创建新的标识符(及其元数据)。最常用的生成器是 rdf_types::generator::Blank
,它创建空白节点标识符。
示例
以下是一个使用 JsonLdProcessor::flatten
对任意 RemoteDocumentReference
进行压缩的示例。
use static_iref::iri;
use json_ld::{JsonLdProcessor, Options, RemoteDocumentReference, syntax::Print};
let input = RemoteDocumentReference::iri(iri!("https://example.com/sample.jsonld").to_owned());
// Use `FsLoader` to redirect any URL starting with `https://example.com/` to
// the local `example` directory. No HTTP query.
let mut loader = json_ld::FsLoader::default();
loader.mount(iri!("https://example.com/").to_owned(), "examples");
let mut generator = rdf_types::generator::Blank::new();
let nodes = input
.flatten(&mut generator, &mut loader)
.await
.expect("flattening failed");
println!("output: {}", nodes.pretty_print());
快速 IRIs 和空白节点标识符
此库为您提供使用任何数据类型来表示 IRIs 和空白节点标识符的机会。大多数类型都进行了参数化。为了避免不必要的分配和昂贵的比较,强烈建议使用便宜、轻量级的类型,如 rdf_types::vocabulary::Index
。此类型将使用唯一索引表示每个不同的 IRI/空白节点标识符。在这种情况下,可以将一个 rdf_types::IndexVocabulary
传递给每个函数,该函数将每个索引映射回其原始 IRI/空白标识符表示形式。
您还可以使用自己的索引类型,使用您自己的rdf_types::Vocabulary
实现。
显示与词汇相关的值
由于使用词汇将IRIs和空白id与其文本表示分离,这使得使用它们显示数据变得复杂。幸运的是,许多由json-ld
定义的类型实现了contextual::DisplayWithContext
特质,允许使用“上下文”显示值,在这里上下文就是词汇。通过导入提供with
方法的contextual::WithContext
,您可以将这样的值显示如下
use static_iref::iri;
use rdf_types::vocabulary::{IriVocabularyMut, IndexVocabulary};
use contextual::WithContext;
let mut vocabulary: IndexVocabulary = IndexVocabulary::new();
let i = vocabulary.insert(iri!("https://docs.rs/contextual"));
let value = rdf_types::Subject::Iri(i);
println!("{}", value.with(&vocabulary))
测试
要首次运行测试,请在shell中使用以下命令
git submodule init
git submodule update
cargo test
这将克隆包含官方测试套件的W3C JSON-LD API存储库,使用json-ld-testing
存储库提供的进程宏生成关联的Rust测试,并运行测试。
之后,简单的cargo test
将重新运行测试。
赞助商
非常感谢SpruceID赞助本项目!
许可
根据以下任一许可进行许可
- Apache License,版本2.0(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确说明,否则根据Apache-2.0许可中定义的,您提交给作品以供包含的任何贡献,都应按上述方式双许可,不附加任何额外条款或条件。
依赖项
~11–23MB
~352K SLoC