知識庫 / JSON / Jackson RSS 訂閱

JSON-LD 超媒體序列化

Data,Jackson
HongKong
6
09:52 PM · Dec 05 ,2025

1. 概述

JSON-LD 是一種基於 JSON 的 RDF 格式,用於表示 鏈接數據。它允許將現有的 JSON 對象擴展為具有超媒體能力,換句話説,具備以機器可讀的方式包含鏈接的能力。

在本教程中,我們將探討一些基於 Jackson 的選項,用於直接將 JSON-LD 格式序列化和反序列化為 POJO。我們還將涵蓋 JSON-LD 的基本概念,以便我們理解示例。

2. 基本概念

首次看到 JSON-LD 文檔時,我們會注意到一些成員名稱以 @ 字符開頭。 這些是 JSON-LD 關鍵字,它們的取值有助於我們理解文檔的其餘部分。

為了在 JSON-LD 的世界中進行導航,並理解本教程,我們需要了解四個關鍵字:

  • @context 是包含一個鍵值映射的 JSON 對象,該映射包含了用於解釋文檔所需的一切;
  • @vocab@context 中的一個可能鍵,它引入了默認詞彙,從而使 @context 對象更短;
  • @id 是用於標識鏈接的關鍵字,既可以作為資源屬性來直接鏈接到資源本身,也可以作為 @type 的值來標記任何字段為鏈接;
  • @type 是用於標識資源類型(在資源級別或在 @context 中);例如,定義嵌入資源的類型;

3. Java 中序列化

在繼續之前,我們應該回顧一下之前的教程,以刷新我們對 Jackson 的 ObjectMapper、Jackson 註解以及自定義 Jackson 序列化器的記憶。

熟悉 Jackson 之後,我們可能會意識到,可以使用 @id@type 註解,輕鬆地在任何 POJO 中序列化兩個自定義字段。然而,手動編寫 @context 可能會耗費大量時間和容易出錯。

因此,為了避免這種容易出錯的方法,讓我們更詳細地瞭解一下我們可以用來生成 @context 的兩個庫。不幸的是,它們都沒有能夠生成所有 JSON-LD 的功能,稍後我們會更詳細地瞭解它們的不足之處。

4. 使用 Jackson-Jsonld 進行序列化

Jackson-Jsonld 是一個 Jackson 模塊,它允許以方便的方式對 POJO 進行註解,從而生成 JSON-LD 文檔。

4.1. Maven 依賴

首先,將 jackson-jsonld 添加為依賴項到 pom.xml 中:

<dependency>
    <groupId>com.io-informatics.oss</groupId>
    <artifactId>jackson-jsonld</artifactId>
    <version>0.1.1</version>
</dependency>

4.2. 示例

然後,讓我們創建一個示例 POJO 併為其進行註釋,以生成 @context

@JsonldResource
@JsonldNamespace(name = "s", uri = "http://schema.org/")
@JsonldType("s:Person")
@JsonldLink(rel = "s:knows", name = "knows", href = "http://example.com/person/2345")
public class Person {
    @JsonldId
    private String id;
    @JsonldProperty("s:name")
    private String name;

    // constructor, getters, setters
}

讓我們逐步分析我們所做的工作:

  • 使用 @JsonldResource 標記POJO為JSON-LD資源的處理對象
  • @JsonldNamespace 中定義了我們希望使用的詞彙的簡寫
  • 我們在 @JsonldType 中指定的參數將成為資源的 @type
  • 我們使用 @JsonldLink 註解添加了指向資源的鏈接。在處理過程中,name 參數將用作字段名稱,並將作為 @context 中的鍵添加到其中。 href 將是字段值,rel 將是 @context 中的映射值
  • 我們標記的字段,使用 @JsonldId 註解,將成為資源的 @id
  • 我們在 @JsonldProperty 中指定的參數將成為字段名稱在 @context 中的映射值

接下來,讓我們生成JSON-LD文檔。

首先,我們應該在 ObjectMapper 中註冊 JsonldModule該模塊包含一個自定義 Serializer,Jackson 將用於標記的 POJO 帶有 @JsonldResource 註解

然後,我們將繼續使用 ObjectMapper 生成JSON-LD文檔:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JsonldModule());

Person person = new Person("http://example.com/person/1234", "Example Name");
String personJsonLd = objectMapper.writeValueAsString(person);

因此,personJsonLd 變量現在應包含:

{
  "@type": "s:Person",
  "@context": {
    "s": "http://schema.org/",
    "name": "s:name",
    "knows": {
      "@id": "s:knows",
      "@type": "@id"
    }
  },
  "name": "Example Name",
  "@id": "http://example.com/person/1234",
  "knows": "http://example.com/person/2345"
}

4.3. 考慮因素

在為項目選擇該庫之前,我們應該考慮以下事項:

  • 使用 <em @vocab</em> 關鍵字不可行,因此我們必須使用 <em @JsonldNamespace</em> 提供字段名稱的簡寫,或者每次都完整地編寫 Internationalized Resource Identifier (IRI)。
  • 我們只能在編譯時定義鏈接,因此為了添加運行時鏈接,我們需要使用反射來修改該註解中的參數。

5. 使用 Hydra-Jsonld 進行序列化

Hydra-Jsonld 是 Hydra-Java 庫中的一個模塊,主要用於為 Spring 應用創建便捷的 JSON-LD 響應。它使用 Hydra 詞彙,使 JSON-LD 文檔更具表達力。

然而Hydra-Jsonld 模塊包含一個 Jackson 序列化器,以及一些註解,我們可以利用它們在 Spring 框架之外生成 JSON-LD 文檔。

5.1. Maven 依賴

首先,將 hydra-jsonld 的依賴添加到 <pom.xml> 中:

<dependency>
    <groupId>de.escalon.hypermedia</groupId>
    <artifactId>hydra-jsonld</artifactId>
    <version>0.4.2</version>
</dependency>

5.2. 示例

其次,讓我們為 POJO 添加註釋以生成 <em @context</em>

Hydra-Jsonld 自動生成默認的 <em @context</em>,無需添加註釋。 <strong>如果對默認值感到滿意,我們只需要添加<em @id` 即可獲得有效的 JSON-LD 文檔。

默認詞彙將是 schema.org 詞彙,<em @type</em> 將是 Java 的 <em class</em> 名稱,以及 POJO 的公共屬性都將包含在生成的 JSON-LD 文檔中。

在這個示例中,讓我們使用自定義值覆蓋這些默認值

@Vocab("http://example.com/vocab/")
@Expose("person")
public class Person {
    private String id;
    private String name;

    // constructor

    @JsonProperty("@id")
    public String getId() {
        return id;
    }

    @Expose("fullName")
    public String getName() {
        return name;
    }
}

再次,讓我們更仔細地看看涉及的步驟:

  • 與 Jackson-Jsonld 示例相比,我們從我們的 POJO 中省略了 knows 字段,因為這與 Hydra-Jsonld 在 Spring Framework 之外的限制有關
  • 我們使用 @Vocab 註解設置了首選詞彙
  • 通過在類上使用 @Expose 註解,我們設置了不同的資源 @type
  • 我們使用 @Expose 註解在屬性上設置其映射到自定義值的 @context
  • 為了從屬性生成 @id,我們使用了 Jackson 中的 @JsonProperty 註解

接下來,讓我們配置一個 Jackson 的 Module 實例,以便將其註冊到 ObjectMapper 中。 我們將 JacksonHydraSerializer 作為 BeanSerializerModifier 添加,以便將其應用於所有正在序列化的 POJO :

SimpleModule getJacksonHydraSerializerModule() {
    return new SimpleModule() {
        @Override
        public void setupModule(SetupContext context) {
            super.setupModule(context);

            context.addBeanSerializerModifier(new BeanSerializerModifier() {
                @Override
                public JsonSerializer<?> modifySerializer(
                  SerializationConfig config, 
                  BeanDescription beanDesc, 
                  JsonSerializer<?> serializer) {
                    if (serializer instanceof BeanSerializerBase) {
                        return new JacksonHydraSerializer((BeanSerializerBase) serializer);
                    } else {
                        return serializer;
                    }
                }
            });
        }
    };
}

然後,我們將在 ObjectMapper 中註冊 Module,並使用它。 此外,我們還應將 ObjectMapper 設置為僅包含非 null 值,以生成有效的 JSON-LD 文檔:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(getJacksonHydraSerializerModule());
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Person person = new Person("http://example.com/person/1234", "Example Name");

String personJsonLd = objectMapper.writeValueAsString(person);

現在,personJsonLd 變量應包含:

{
  "@context": {
    "@vocab": "http://example.com/vocab/",
    "name": "fullName"
  },
  "@type": "person",
  "name": "Example Name",
  "@id": "http://example.com/person/1234"
}

5.3. 考慮因素

雖然在 Spring 框架之外使用 Hydra-Jsonld 在技術上是可行的,但它最初的設計是為了與 Spring-HATEOAS 配合使用。因此,無法像 Jackson-Jsonld 那樣生成帶有註解的鏈接。另一方面,對於一些 Spring 相關的類,它們會自動生成鏈接。

在選擇該庫用於項目之前,我們應該考慮以下事項:

  • 使用它與 Spring 框架一起將啓用額外的功能
  • 如果未使用 Spring 框架,則無法輕鬆生成鏈接
  • 我們無法禁用 @vocab 的使用,只能對其進行覆蓋

6. 使用 Jsonld-Java 和 Jackson 進行反序列化

Jsonld-Java 是 JSON-LD 1.0 規範和 API 的 Java 實現,但不幸的是,它不是最新的版本。

對於 1.1 規範版本的實現,請查看 Titanium JSON-LD 庫。

要反序列化一個 JSON-LD 文檔,我們可以使用 JSON-LD API 中的一項特性——“壓縮”(compaction)將其轉換為我們可以使用 ObjectMapper 映射到 POJO 的格式。

6.1. Maven 依賴

首先,添加 jsonld-java 的依賴:

<dependency>
    <groupId>com.github.jsonld-java</groupId>
    <artifactId>jsonld-java</artifactId>
    <version>0.13.0</version>
</dependency>

6.2. 示例

讓我們使用以下 JSON-LD 文檔作為輸入:

{
  "@context": {
    "@vocab": "http://schema.org/",
    "knows": {
      "@type": "@id"
    }
  },
  "@type": "Person",
  "@id": "http://example.com/person/1234",
  "name": "Example Name",
  "knows": "http://example.com/person/2345"
}

為了簡化起見,我們假設文檔的內容存儲在一個名為 inputJsonLdString 變量中。

首先,我們對其進行壓縮並將其轉換回 String

Object jsonObject = JsonUtils.fromString(inputJsonLd);
Object compact = JsonLdProcessor.compact(jsonObject, new HashMap<>(), new JsonLdOptions());
String compactContent = JsonUtils.toString(compact);
<ul>
 <li>我們可以使用來自 <em >JsonUtils</em > 的方法解析和寫入 JSON-LD 對象,JsonUtils 是 Jsonld-Java 庫的一部分</li>
 <li>在使用 <em >compact</em> 方法時,我們可以將一個空 <em >Map</em> 作為第二個參數。 這樣,壓縮算法將產生一個簡單的 JSON 對象,其中鍵已解析為 IRI 形式</li>
</ul>
<p><strong > <em >compactContent</em > 變量應包含:</strong></p>
{
  "@id": "http://example.com/person/1234",
  "@type": "http://schema.org/Person",
  "http://schema.org/knows": {
    "@id": "http://example.com/person/2345"
  },
  "http://schema.org/name": "Example Name"
}

其次,讓我們使用 Jackson 註解定製 POJO,以適應這種文檔結構:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Person {
    @JsonProperty("@id")
    private String id;
    @JsonProperty("http://schema.org/name")
    private String name;
    @JsonProperty("http://schema.org/knows")
    private Link knows;

    // constructors, getters, setters

    public static class Link {
        @JsonProperty("@id")
        private String id;

        // constructors, getters, setters
    }
}

最後,讓我們將 JSON-LD 映射到 POJO:

ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.readValue(compactContent, Person.class);

7. 結論

在本文中,我們探討了兩種基於 Jackson 的庫,用於將 POJO 序列化為 JSON-LD 文檔,以及一種將 JSON-LD 序列化為 POJO 的方法。

正如我們所強調的,這兩個序列化庫都存在一些不足之處,我們在使用它們之前應該加以考慮。 如果我們需要使用 JSON-LD 的更多功能,這些庫無法提供,我們可以通過使用 RDF 庫,並指定 JSON-LD 輸出格式來創建我們的文檔。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.