JSON-LD 超媒體序列化

Data,Jackson
Remote
1
10:02 PM · Nov 30 ,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. Serialization With Jackson-JsonldJackson-Jsonld is a Jackson module that enables the annotation of POJOs in a convenient way to generate JSON-LD documents.

4.1. Maven DependenciesFirst, let’s add jackson-jsonld as a dependency to the pom.xml:


    com.io-informatics.oss
    jackson-jsonld
    0.1.1
]]>

4.2. ExampleThen, let’s create our example POJO and annotate it for @context generation:

@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
}

Let’s deconstruct the steps to understand what we’ve done:

With @JsonldResource we marked the POJO for processing as a JSON-LD resourceIn the @JsonldNamespace we defined a shorthand for the vocabulary we want to useThe parameter we specified in @JsonldType will become the @type of the resourceWe used the @JsonldLink annotation to add links to the resource. When processed, the name parameter will be used as a field name and also added as a key to the @context. href will be the field value and rel will be the mapped value in the @contextThe field we marked with @JsonldId will become the @id of the resourceThe parameter we specified in @JsonldProperty will become the value mapped to the field’s name in the @context

Next, let’s generate the JSON-LD document.

First, we should register the JsonldModule in the ObjectMapper. This module contains a custom Serializer that Jackson will use for POJOs marked with the @JsonldResource annotation.

Then, we’ll continue and use the ObjectMapper to generate the JSON-LD document:

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

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

As a result, the personJsonLd variable should now contain:

{
  "@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. ConsiderationsBefore we choose this library for a project, we should consider the following:

Using the @vocab keyword is not possible, so we’ll have to either use the @JsonldNamespace to provide a shorthand for resolving field names or write out the full Internationalized Resource Identifier (IRI) every timeWe can only define links at compile-time, so in order to add a link runtime, we would need to use reflection to change that parameter in the annotation

5. Serialization With Hydra-Jsonld

Hydra-Jsonld 是 Hydra-Java 庫的一個模塊,主要用於為 Spring 應用程序創建方便的 JSON-LD 響應。

它使用 Hydra Vocabulary 使 JSON-LD 文檔更具表現力。

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

5.1. Maven Dependencies

首先,讓我們將 hydra-jsonld 依賴添加到 pom.xml 中:

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

5.2. Example

其次,讓我們為 POJO 註釋生成 @context:

@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 框架之外的限制。
  • 我們使用 @Vocab 註解設置了我們的首選詞彙。
  • 通過在類上使用 @Expose 註解,我們設置了不同的資源 @type。
  • 我們使用 @Expose 註解在一個屬性上設置其映射到 @context 中的自定義值。
  • 為了從屬性中生成 @id,我們使用了 Jackson 的 @JsonProperty 註解。

接下來,讓我們配置一個可以註冊到 ObjectMapper 中的 Jackson 模塊。我們將 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 中註冊模塊並使用它。我們還應該將 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. Considerations

雖然在技術上可以使用 Hydra-Jsonld 在 Spring 框架之外,但它最初是為了與 Spring-HATEOAS 配合而設計的。因此,我們無法使用註解生成鏈接,就像在 Jackson-Jsonld 中看到的那樣。另一方面,它們對於某些 Spring 特定類自動生成。

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

  • 使用它與 Spring 框架一起將啓用附加功能。
  • 如果未使用 Spring 框架,則沒有簡單的方法來生成鏈接。
  • 我們無法禁用 @vocab 的使用,只能覆蓋它。

6. Deserialization With Jsonld-Java and Jackson

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

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

要反序列化一個 JSON-LD 文檔,讓我們使用 JSON-LD API 功能“壓縮”將其轉換為可以映射到 POJO 的格式,使用 ObjectMapper

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"
}

為了簡化,假設文檔的內容存儲在 String 變量 inputJsonLd 中。

首先,讓我們壓縮它並將其轉換回 String


Object jsonObject = JsonUtils.fromString(inputJsonLd);
Object compact = JsonLdProcessor.compact(jsonObject, new HashMap<>(), new JsonLdOptions());
String compactContent = JsonUtils.toString(compact);
  • 我們可以使用 Jsonld-Java 庫中的 JsonUtils 方法解析和寫入 JSON-LD 對象
  • 在使用 compact 方法時,作為第二個參數,我們可以使用一個空 Map。 這樣,壓縮算法將產生一個簡單的 JSON 對象,其中鍵已解析為 IRI 形式

compactContent 變量應包含:


{
  "@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"
}

其次,讓我們根據此結構定製我們的 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.