1. Overview
1.概述
JSON-LD is a JSON-based RDF format for representing Linked Data. It enables extending existing JSON objects with hypermedia capabilities; in other words, the capability to contain links in a machine-readable way.
JSON-LD是一种基于JSON的RDF格式,用于表示链接数据。它能够用超媒体功能扩展现有的JSON对象;换句话说,它能够以机器可读的方式包含链接。
In this tutorial, we’ll look at a couple of Jackson-based options to serialize and deserialize the JSON-LD format directly into POJOs. We’ll also cover the basic concepts of JSON-LD that will enable us to understand the examples.
在本教程中,我们将看看几个基于Jackson的选项,将JSON-LD格式直接序列化和反序列化为POJO。我们还将介绍JSON-LD的基本概念,这将使我们能够理解这些例子。
2. Basic Concepts
2.基本概念
The first time we see a JSON-LD document, we notice that some member names start with the @ character. These are JSON-LD keywords, and their values help us to understand the rest of the document.
当我们第一次看到JSON-LD文档时,我们注意到一些成员的名字以@字符开始。这些是JSON-LD的关键字,它们的值有助于我们理解文档的其余部分。
To navigate the world of JSON-LD and to understand this tutorial, we need to be aware of four keywords:
为了浏览JSON-LD的世界和理解本教程,我们需要注意四个关键词。
- @context is the description of the JSON object that contains a key-value map of everything needed for the interpretation of the document
- @vocab is a possible key in @context that introduces a default vocabulary to make the @context object much shorter
- @id is the keyword to identify links either as a resource property to represent the direct link to the resource itself or as a @type value to mark any field as a link
- @type is the keyword to identify resource types either on the resource level or in the @context; for example, to define the type of embedded resources
3. Serialization in Java
3.Java中的序列化
Before we continue, we should take a look at our previous tutorials to refresh our memory on the Jackson ObjectMapper, Jackson Annotations, and custom Jackson Serializers.
在我们继续之前,我们应该看一下我们之前的教程,以刷新我们对Jackson ObjectMapper, Jackson Annotations,以及custom Jackson Serializers。
Being already familiar with Jackson, we might realize that we could easily serialize two custom fields in any POJO as @id and @type using the @JsonProperty annotation. However, writing the @context by hand could be a lot of work and also prone to error.
由于已经熟悉了Jackson,我们可能会意识到,我们可以使用@JsonProperty注解轻松地将任何POJO中的两个自定义字段序列化为@id和@type。然而,手工编写@context可能是一个很大的工作,也容易出错。
Therefore, to avoid this error-prone approach, let’s take a closer look at two libraries that we could use for @context generation. Unfortunately, neither one of them is capable of generating all features of JSON-LD, but we’ll take a look at their shortcomings later as well.
因此,为了避免这种容易出错的方法,让我们仔细看看两个我们可以用来生成@context的库。不幸的是,它们都不能生成JSON-LD的所有功能,但我们也会在后面看看它们的缺点。
4. Serialization With Jackson-Jsonld
4.用Jackson-Jsonld进行序列化
Jackson-Jsonld is a Jackson module that enables the annotation of POJOs in a convenient way to generate JSON-LD documents.
Jackson-Jsonld是一个Jackson模块,它能够以一种方便的方式对POJO进行注释,以生成JSON-LD文档。。
4.1. Maven Dependencies
4.1.Maven的依赖性
First, let’s add jackson-jsonld as a dependency to the pom.xml:
首先,让我们把jackson-jsonld作为一个依赖项添加到pom.xml。
<dependency>
<groupId>com.io-informatics.oss</groupId>
<artifactId>jackson-jsonld</artifactId>
<version>0.1.1</version>
</dependency>
4.2. Example
4.2.例子
Then, let’s create our example POJO and annotate it for @context generation:
然后,让我们创建我们的示例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
}
Let’s deconstruct the steps to understand what we’ve done:
让我们来解构这些步骤,以了解我们做了什么。
- With @JsonldResource we marked the POJO for processing as a JSON-LD resource
- In the @JsonldNamespace we defined a shorthand for the vocabulary we want to use
- The parameter we specified in @JsonldType will become the @type of the resource
- We 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 @context
- The field we marked with @JsonldId will become the @id of the resource
- The 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.
接下来,让我们生成JSON-LD文档。
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.
首先,我们应该在ObjectMapper中注册JsonldModule。该模块包含一个自定义的序列化器,Jackson将对标有@JsonldResource注解的POJO进行使用。
Then, we’ll continue and use the ObjectMapper to generate the JSON-LD document:
然后,我们将继续并使用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);
As a result, the personJsonLd variable should now contain:
结果,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. Considerations
4.3.考虑因素
Before 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 time
- We 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
5.使用Hydra-Jsonld进行序列化
Hydra-Jsonld is a module of the Hydra-Java library, which is primarily built to enable convenient JSON-LD response creation for Spring applications. It uses the Hydra Vocabulary to make the JSON-LD documents more expressive.
Hydra-Jsonld是Hydra-Java库的一个模块,它的建立主要是为了使Spring应用程序能够方便地创建JSON-LD响应。它使用Hydra Vocabulary来使JSON-LD文档更具表达力。
However, the Hydra-Jsonld module contains a Jackson Serializer and some annotations that we can use to generate JSON-LD documents outside of the Spring Framework.
然而,Hydra-Jsonld模块包含一个Jackson Serializer和一些注释,我们可以用它来生成Spring框架之外的JSON-LD文档。
5.1. Maven Dependencies
5.1.Maven的依赖性
First, let’s add the dependency for hydra-jsonld to the pom.xml:
首先,让我们把hydra-jsonld的依赖性添加到pom.xml。
<dependency>
<groupId>de.escalon.hypermedia</groupId>
<artifactId>hydra-jsonld</artifactId>
<version>0.4.2</version>
</dependency>
5.2. Example
5.2.例子
Secondly, let’s annotate our POJO for @context generation.
其次,让我们对我们的POJO进行注释,以便生成@context。
Hydra-Jsonld automatically generates a default @context without the need for annotations. If we’re satisfied with the defaults, we only need to add the @id to get a valid JSON-LD document.
Hydra-Jsonld自动生成一个默认的@context,而不需要注释。如果我们对默认值感到满意,我们只需要添加@id来获得一个有效的JSON-LD文档。
The default vocabulary will be the schema.org vocabulary, the @type the Java class name, and the public properties of the POJO will all be included in the resulting JSON-LD document.
默认的词汇表将是schema.org词汇表,@type是Javaclass名称,POJO的公共属性将全部包含在生成的JSON-LD文档中。
In this example, let’s override these defaults with custom values:
在这个例子中,让我们用自定义值覆盖这些默认值。
@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;
}
}
Again, let’s take a closer look at the steps involved:
再次,让我们仔细看看其中的步骤。
- Compared to the Jackson-Jsonld example, we left out the knows field from our POJO because of the limitations of Hydra-Jsonld outside of the Spring Framework
- We set our preferred vocabulary with the @Vocab annotation
- By using the @Expose annotation on the class, we set a different resource @type
- We used the same @Expose annotation on a property to set its mapping to a custom value in the @context
- For generating the @id from a property, we used the @JsonProperty annotation from Jackson
Next, let’s configure an instance of a Jackson Module that we can register in the ObjectMapper. We’ll add the JacksonHydraSerializer as a BeanSerializerModifier so it can be applied to all POJOs that are being serialized:
接下来,让我们配置一个 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;
}
}
});
}
};
}
Then let’s register the Module in ObjectMapper and use it. We should also set the ObjectMapper to only include non-null values to produce a valid JSON-LD document:
然后让我们在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);
Now, the personJsonLd variable should contain:
现在,personJsonLd变量应该包含:。
{
"@context": {
"@vocab": "http://example.com/vocab/",
"name": "fullName"
},
"@type": "person",
"name": "Example Name",
"@id": "http://example.com/person/1234"
}
5.3. Considerations
5.3.考虑因素
Although it’s technically possible to use Hydra-Jsonld outside of the Spring Framework, it was originally designed for usage with Spring-HATEOAS. As a result, there’s no way to generate links with annotations as we saw in Jackson-Jsonld. On the other hand, they are generated for some Spring-specific classes automatically.
虽然在技术上可以在Spring框架之外使用Hydra-Jsonld,但它最初是为配合Spring-HATEOAS使用而设计的。因此,没有办法像我们在Jackson-Jsonld中看到的那样生成带有注解的链接。另一方面,它们是为一些Spring特定的类自动生成的。
Before we choose this library for a project, we should consider the following:
在我们为一个项目选择这个库之前,我们应该考虑以下几点。
- Using it with the Spring Framework will enable additional features
- There’s no easy way to generate links if we’re not using the Spring Framework
- We cannot disable the usage of @vocab, we can only override it
6. Deserialization With Jsonld-Java and Jackson
6.用Jsonld-Java和Jackson进行反序列化
Jsonld-Java is the Java implementation of the JSON-LD 1.0 specification and API, which is unfortunately not the latest version.
Jsonld-Java是JSON-LD 1.0规范和API的Java实现,遗憾的是这不是最新版本。
For an implementation of the 1.1 specification version, have a look at the Titanium JSON-LD library.
对于1.1规范版本的实现,请看Titanium JSON-LD库。
To deserialize a JSON-LD document, let’s transform it with a JSON-LD API feature, called compaction, to a format that we can map to a POJO with ObjectMapper.
为了反序列化一个JSON-LD文档,让我们用JSON-LD API的一个特性(称为压实)将其转换为一种我们可以用ObjectMapper映射到POJO的格式。
6.1. Maven Dependencies
6.1.Maven的依赖性
First, let’s add the dependency for jsonld-java:
首先,让我们添加jsonld-java的依赖性。
<dependency>
<groupId>com.github.jsonld-java</groupId>
<artifactId>jsonld-java</artifactId>
<version>0.13.0</version>
</dependency>
6.2. Example
6.2.例子
Let’s work with this JSON-LD document as our input:
让我们用这个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"
}
For the sake of simplicity, let’s assume we have the content of the document in a String variable called inputJsonLd.
为了简单起见,让我们假设我们在一个名为inputJsonLd的String变量中拥有文档的内容。
First, let’s compact it and convert it back to a String:
首先,让我们压缩它并将其转换回String。
Object jsonObject = JsonUtils.fromString(inputJsonLd);
Object compact = JsonLdProcessor.compact(jsonObject, new HashMap<>(), new JsonLdOptions());
String compactContent = JsonUtils.toString(compact);
- We can parse and write the JSON-LD object with methods from the JsonUtils, which is part of the Jsonld-Java library
- When using the compact method, as a second parameter we can use an empty Map. This way, the compaction algorithm will produce a simple JSON object where the keys are resolved to their IRI forms
The compactContent variable should contain:
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"
}
Secondly, let’s tailor our POJO with Jackson annotations to fit such a document structure:
其次,让我们用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
}
}
And finally, let’s map the JSON-LD to the POJO:
最后,让我们把JSON-LD映射到POJO上。
ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.readValue(compactContent, Person.class);
7. Conclusion
7.结论
In this article, we looked at two Jackson-based libraries for serializing a POJO into a JSON-LD document, and one way to deserialize a JSON-LD into a POJO.
在这篇文章中,我们看了两个基于Jackson的库,用于将POJO序列化为JSON-LD文档,以及一种将JSON-LD反序列化为POJO的方法。
As we’ve highlighted, both serialization libraries have shortcomings that we should consider before using them. If we need to use more features of JSON-LD than these libraries can offer, we could approach creating our document via an RDF library with JSON-LD output format.
正如我们所强调的,这两个序列化库都有缺点,我们在使用它们之前应该考虑。如果我们需要使用JSON-LD的更多功能,而不是这些库所能提供的,我们可以通过一个具有JSON-LD输出格式的RDF库来创建我们的文档。
As usual, the source code can be found over on GitHub.
像往常一样,源代码可以在GitHub上找到over。