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-alpha2020 年 4 月 27 日

#56 in 网页编程

Download history 1518/week @ 2024-04-28 1738/week @ 2024-05-05 1369/week @ 2024-05-12 1572/week @ 2024-05-19 1270/week @ 2024-05-26 1560/week @ 2024-06-02 1142/week @ 2024-06-09 2003/week @ 2024-06-16 1928/week @ 2024-06-23 822/week @ 2024-06-30 1671/week @ 2024-07-07 1235/week @ 2024-07-14 1413/week @ 2024-07-21 1636/week @ 2024-07-28 1781/week @ 2024-08-04 1720/week @ 2024-08-11

6,581 每月下载量
用于 58 个 Crates (7 直接)

MIT/Apache

2.5MB
24K SLoC

Rust 的 JSON-LD 实现

GitHub Actions Workflow Status Crate informations Crates.io MSRV License Documentation

此包是 JSON-LD 数据交换格式的 Rust 实现。

Linked Data (LD) 是基于标准网页技术建立的 万维网联盟 (W3C) 创新项目,旨在创建一个跨网页的互相关联数据集网络。 JavaScript 对象表示法 (JSON) 是一种广泛使用的简单、非结构化数据序列化格式,用于以可读的方式描述数据对象。JSON-LD 将这两种技术结合在一起,为 JSON 添加语义,创建一种轻量级的数据序列化格式,可以组织数据并帮助网页应用程序在大规模上实现互操作性。

用法

此库的入口点是提供对所有 JSON-LD 转换算法(上下文处理、展开、压缩等)访问的 JsonLdProcessor 特性。如果您想探索和/或转换 ExpandedDocument,您可能还想查看代表 JSON 对象的 Object 类型。

展开

如果您想展开一个 JSON-LD 文档,首先使用 RemoteDocumentRemoteDocumentReference 描述要展开的文档。

  • 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-2.0许可中定义的,您提交给作品以供包含的任何贡献,都应按上述方式双许可,不附加任何额外条款或条件。

依赖项

~11–23MB
~352K SLoC