内容


JSON Binding API 入门,第 2 部分

通过 JSON-B 自定义绑定

通过和注解运行时配置来自定义 JSON 绑定

Comments

系列内容:

此内容是该系列 2 部分中的第 # 部分: JSON Binding API 入门,第 2 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:JSON Binding API 入门,第 2 部分

敬请期待该系列的后续内容。

本系列的第一篇文章概述了 JSON-B,包括初步介绍如何使用注解和运行时配置来自定义绑定行为。本文将提供这两种机制的更深入的、实践性的介绍。您将学习如何分开或结合使用注解和运行时配置,以及如何理解它们在自定义解决方案中的相互作用。您还将初步了解 JSON-B 适配器、低级别序列化器和反序列化器,您可以使用它们来自定义 JSON-B 中的操作逻辑。

两种自定义 JSON-B 的方式(复习)

可结合或分开使用注解和运行时配置来自定义 Java™ 企业应用程序中的 JSON 绑定。如果您已经阅读了第 1 部分,以下代码样本应该会加深您对模型工作原理的记忆。

编译时注解

JSON-B 提供了许多内置注解,您可以使用它们来标记您希望启用自定义行为的字段、类、参数或 setter/getter。清单 1 是一个示例。

清单 1. 使用注解模型的示例
public class Book {
  @JsonbProperty("isbn")
  public String id;
}

在这里,序列化的 JSON 文档中的 id 字段名称将被重命名为 isbn。要成功反序列化为 Book 实例,JSON 文档必须有一个名为 isbn 的属性。

运行时配置

如果您更喜欢运行时配置而不是注解,可以构建一个配置策略,并将它传递给用来执行序列化和反序列化的 Jsonb 实例。此方法如清单 2 所示。

清单 2. 使用运行时模型的示例
JsonbConfig jsonbConfig = new JsonbConfig()
   .withPropertyNamingStrategy(
     PropertyNamingStrategy.LOWER_CASE_WITH_DASHES);

String json = JsonbBuilder.create(jsonbConfig).toJson(book);

在清单 2 中,可以看到在 JsonbConfig 实例上设置了属性命名策略,然后该策略被传递给创建 JsonBuilder 实例的工厂方法。 当使用创建的 Jsonb 实例执行序列化或反序列化时,就会使用该属性命名策略。在本例中,属性名称被转换为小写并用连字符分隔。

自定义属性名称

属性的名称取决于相应 Java bean 的字段名称。在执行序列化时,该字段名称被用作输出 JSON 文档中的属性名称。在执行反序列化时,属性名称与字段名称相匹配,而且会调用适当的 setter,或设置一个公共字段。

在某些情况下,默认命名策略不太适合您尝试解决的问题。JSON 文档的命名约定可能不同于您的业务实体使用的命名约定,或者,您可能需要将数据导出为与业务对象的结构不匹配的 JSON 文档格式。

无论是哪种情况,自定义属性名称都是提高序列化和反序列化灵活性的一种途径。实现此目标的一种方法是在字段、参数、getter 或 setter 上使用 @JsonbProperty 注解。在这种情况下,自定义的名称会作为值传递给注解。需要知道的一些规则:

  • 如果将注解放在一个字段上,那么自定义的名称可同时用于序列化和反序列化。
  • 如果将注解放在一个 setter 方法上,那么自定义的名称仅能用于反序列化。
  • 如果将注解放在一个 getter 方法上,那么它仅能用于序列化。

清单 3 给出了针对上一篇文章中介绍的 Book 类的 idtitleauthor 字段进行了自定义的属性名称。

清单 3. 使用 @JsonbProperty 注解的 Book 类
public class Book {

  @JsonbProperty("isbn")
  private String id;
  private String title;
  private String author;

  @JsonbProperty("bookTitle")
  public String getTitle() {
      return title;
  }

  @JsonbProperty("authorName")
  public void setAuthor(String author) {
      this.author = author;
  }

  // other getters and setters omitted for brevity
}

执行 Book 实例的序列化会得到一个类似清单 4 的 JSON 文档。

清单 4. JSON 文档中的序列化 Book 实例
{
 "author": "Alex Theedom",
 "bookTitle": "Fun with JSON-B",
 "isbn": "ABC-123-XYZ"
}

请注意,在清单 4 中,author 字段的名称保持未变。这是因为仅对清单 3 中的 Book 类的 setter 方法进行了注解。因此,@JsonbProperty 和 getter 方法仅在反序列化期间调用。要成功地将清单 4 中的 JSON 文档反序列化为 Book 实例,需要手动将 author 字段编辑为 authorName

也可以对序列化和反序列化使用不同的自定义名称,或者在同一个 POJO 中的字段、getter 和 setter 上使用不同的自定义名称。在这种情况下,一定要知道 getter 和 setter 上的自定义将优先于字段上的自定义。

自定义属性命名策略

如何将字段名称转换为属性取决于属性命名策略。默认情况下,转换后的名称保持不变,但您可以自定义它。例如,可以选择使用下划线分隔属性名称或将它转换为小写。表 1(下表)给出了属性命名策略的完整列表。

可以通过设置 JsonbConfig 实例上的合适值,为运行时模型配置属性命名策略。此过程如清单 5 所示。

清单 5. 配置属性命名策略
public class Magazine {
  private String title;
  private Author authorName;
  private String internalAuditCode;
  private String alternativetitle;
  // getters and setters omitted for brevity
}

Magazine magazine = 
  new Magazine("Fun with JSON binding",
               new Author("Alex", "Theedom"),
               "ABC-123","Fun with JSON-B
               ");

JsonbConfig jsonbConfig = new JsonbConfig()
      .withPropertyNamingStrategy(
           PropertyNamingStrategy.LOWER_CASE_WITH_DASHES);

String json = JsonbBuilder.create(jsonbConfig).toJson(magazine);

清单 5 中的策略将所有字段名转换为小写,并使用连字符界定大小写差异。清单 6 显示了输出。

清单 6. LOWER_CASE_WITH_DASHES 序列化策略
{
  "alternativetitle": "Fun with JSON-B",
  "author-name": {
    "first-name": "Alex",
    "last-name": "Theedom"
  },
  "title": "Fun with JSON binding"
}

有 6 种属性命名策略可供选择,表 1 中总结了这些策略。

表 1. 属性命名策略
策略说明原始名称转换后的属性名称
IDENTITY名称保持不变(默认策略)。authorNameauthorName
LOWER_CASE_WITH_DASHES名称转换为小写并使用连字符界定大小写差异。authorName
alternativetitle
author-name
alternativetitle
LOWER_CASE_WITH_UNDERSCORES名称转换为小写并使用下划线界定大小写差异。authorName
alternativetitle
author_name
alternativetitle
UPPER_CAMEL_CASE第一个字符大写。authorName
alternativetitle
AuthorName
Alternativetitle
UPPER_CAMEL_CASE_WITH_SPACES第一个字符大写并用空格界定大小写差异。authorName
alternativetitle
Author Name
Alternativetitle
CASE_INSENSITIVE使用身份策略来实现序列化,但对于反序列化,属性名称是不区分大小写的。AuthorNAME
对应于
authorName

另请注意,配置了 @JsonbProperty 注解的字段优先于 JsonbConfig 上指定的在运行时配置的命名策略。

自定义属性顺序策略

默认情况下,属性在 JSON 文档中是按词典顺序显示的。表 2 中给出了该策略和另外两个属性顺序策略。

表 2. 默认的和自定义的属性顺序策略
策略说明
LEXICOGRAPHICAL属性按词典顺序排序(默认策略)。
ANY无法保证属性的顺序。
REVERSE属性按词典逆序排序。

如果您想使用运行时模型来配置属性顺序策略,可以在 JsonbConfig 实例上设置合适的策略来完成此操作。在清单 7 中,我们将属性顺序策略设置为词典逆序。

清单 7. 使用 REVERSE 属性顺序策略执行序列化
Magazine magazine = 
    new Magazine("Fun with JSON binding", 
        new Author("Alex", "Theedom"), 
        "Fun with JSON-B");

JsonbConfig jsonbConfig = new JsonbConfig()
      .withPropertyOrderStrategy(PropertyOrderStrategy.REVERSE);

String json = JsonbBuilder.create(jsonbConfig).toJson(magazine);

清单 8 给出了此策略的 JSON 输出。

清单 8. REVERSE 属性顺序策略的输出
{
 "title": "Fun with JSON binding",
 "authorName": {
   "lastName": "Theedom",
   "firstName": "Alex"
 },
 "alternativeTitle": "Fun with JSON-B"
}

另一个选项是使用 @JsonbPropertyOrder 注解来显式指定想要的属性顺序。在这种情况下,可以将属性名称列表传递给 @JsonbPropertyOrder 注解,如清单 9 所示。列表上未指定的属性在有序属性后按词典顺序列出。

清单 9. 使用 @JsonbPropertyOrder 的 Book 实例的输出
@JsonbPropertyOrder(value = {"id", "title", "author"})
public class Book {
  private String id;
  private String title;
  private String author;
  // getters and setters omitted for brevity
}

在清单 9 中,可以看到应用于清单 3 中的指定属性的自定义排序逻辑。@JsonbPropertyOrder 指定的顺序优先于默认的属性顺序策略以及所有运行时配置。新策略适用于已重命名的属性名称。

自定义字段可视性

JSON Binding 使开发人员能精确控制序列化和反序列化过程中的字段可视性和包含与否。

例如,使用 @JsonbTransient 注解的字段不包含在 JSON 文档中,并会在反序列化期间被忽略。只有字段和 getter/setter 方法可采用这种注解方式。在类级别进行注解是无效或不合理的。

也可以配置类的字段的可视性特征。默认情况下,只有公共字段和 getter/setter 方法用于序列化和反序列化,但您可以将访问权自定义得更严格或更宽松。

字段可视性策略是在 PropertyVisibilityStrategy 接口的自定义实现中定义的,其中两个重载的方法 —isVisible(Field)isVisibile(Method)— 控制了对各个字段或方法值的访问权。清单 10 给出了一个示例实现。

清单 10. PropertyVisibilityStrategy 的一个示例实现
PropertyVisibilityStrategy vis = new PropertyVisibilityStrategy() {
  @Override
  public boolean isVisible(Field field) {
      return Modifier.isProtected(field.getModifiers());
  }

  @Override
  public boolean isVisible(Method method) {
      return !method.getName().contains("AlternativeTitle");
  }
};

JsonbConfig 实例上设置了一个 PropertyVisibilityStrategy 类型的实例,如清单 11 所示。

清单 11. 配置序列化来使用 PropertyVisibilityStrategy
Magazine magazine = 
    new Magazine("Fun with JSON binding", 
    new Author("Alex", "Theedom"), 
    "Fun with JSON-B");

JsonbConfig jsonbConfig = new JsonbConfig()
      .withPropertyVisibilityStrategy(vis);

String json = JsonbBuilder.create(jsonbConfig).toJson(magazine);

isVisible() 方法

在序列化过程中,会使用反射来遍历该对象,并将每个 getter 方法对象传递给 isVisible() 方法。在此方法中,可以编写逻辑来确定是否调用该方法。如果调用该方法,则返回 true 来表明该方法的返回值应包含在 JSON 文档输出中。在清单 10 中,当传递 getAlternativeTitle() 方法时,isVisible() 方法返回 false,因此相关字段不会包含在 JSON 输出中。对于其他所有方法,该方法返回了 true,因此将包含它们的属性值。

在上面的示例中不会调用接受某个字段的 isVisible() 方法,因为序列化操作被配置为调用 JavaBean 方法。如果不存在 bean 方法,序列化器和反序列化器会尝试访问实例的公共字段。

在这种情况下,我使用了仅启用带 protected 修饰符字段的代码来覆盖 isVisible() 方法。在 Java 实例没有任何 bean 方法的情况下,仅访问带 protected 修饰符的字段并将它们包含在输出的 JSON 文档中。

自定义 null 处理

在序列化时,含 null 值的对象字段会被忽略,而且默认情况下会保留集合中的 null 值。在反序列化期间,JSON 属性中的 null 将相应的对象字段设置为 null。如果目标字段是 Optional,该值将被设置为 Optional.empty()。可通过 3 种方式自定义这种默认行为。

使用 @JsonbNillable

第一种选择是使用 @JsonbNillable 来注解包或类。这种自定义适用于整个包或类中的所有字段,而且所有 null 都会在序列化和反序列化期间保留。在清单 12 中,使用 @JsonbNillabletitle 字段进行了注解。

清单 12. 具有用 @JsonbNillable 注解的 title 字段的 Book 类
public class Book {
  private String id;
  @JsonbNillable
  private String title;
  private String author;
  // getters and setters omitted for brevity
}

使用 nillable 标签

实现相同解决方案的另一种方法是使用 @JsonbProperty 对相关字段或 JavaBean 属性进行注解,并将它的 nillable 标志设置为 true,如清单 13 所示。

清单 13. 具有用 @JsonbProperty 注解的 authorName 字段的 Magazine 类
public class Magazine {
  private String title;
  @JsonbProperty(nillable = true)
  private Author authorName;
  private String alternativeTitle;
  // getters and setters omitted for brevity
}

发生配置冲突时,会优先选择具有最小范围的注解。因此,具有 nillable = false@JsonbProperty 注解优先于应用于类的 @JsonbNillable 注解。

使用 withNullValues()

自定义 null 处理的最后一种方法是将 truefalse 传递给 JsonbConfig 实例上的 withNullValues() 方法。清单 14 给出了一个将 null 值设置为 trueJsonbConfig 实例的配置。

清单 14. 配置一个将 null 值设置为 true 的 JsonbConfig 实例
JsonbConfig jsonbConfig = new JsonbConfig().withNullValues(true);
Booklet booklet = new Booklet("Fun with Java EE", null, null);
String json = JsonbBuilder.create(jsonbConfig).toJson(booklet);

Booklet 实例的输出 JSON 文档如清单 15 所示。

清单 15. 显示了保留的 null 值的 JSON 文档
{
 "author": {
   "firstName": null,
   "lastName": null
 },
 "title": "Fun with Java EE"
}

自定义对象创建

JSON-B 期望所有类都有一个公共无参数构造函数,它在反序列化期间使用该函数来实例化目标类。创建该实例后,会通过调用合适的 setter 方法或直接设置公共字段,在实例中填充来自 JSON 文档的数据。

这种做法适用于大多数简单场景,但不足以实现更复杂的构造。对于这些情况,需要实现一个自定义构造函数或静态工厂方法。清单 16 给出了这样一个自定义构造函数。

清单 16. 自定义构造函数
public class Magazine {
  private String title;
  private Author authorName;

  @JsonbCreator
  public Magazine(@JsonbProperty("bookTitle") String title,
                  @JsonbProperty("firstName") String firstName,
                  @JsonbProperty("surname") String lastName) {
      this.title = title;
      this.authorName = new Author(firstName, lastName);
  }
  // getters and setters omitted for brevity
}

请注意,这里使用了 @JsonbProperty 注解来将 JSON 属性名称映射到构造函数的参数列表中的参数。清单 17 中的 JSON 文档已成功反序列化为清单 16 中的 Magazine 类。

清单 17. Magazine JSON 文档
{
 "firstName": "Alex",
 "surname": "Theedom",
 "bookTitle": "Fun with JSON-B"
}

在介绍 JSON-B 适配器的小节中,我还将演示序列化和反序列化过程的一种更复杂的自定义。

自定义日期和时间格式

无论如何,处理日期和时间可能是一件头疼的事。幸运的是,新的 JSON Binding API 提供了一个特性包,让自定义这些格式变得更轻松。

可以使用注解 @JsonbDateFormat 在每个级别(从包到字段)上配置日期和时间格式。在清单 18 中,我们仅注解了 setter 方法,以便仅在反序列化期间应用日期格式。如果仅注解了 getter 方法,日期格式仅在序列化期间会得到应用。

清单 18. 仅针对反序列化进行了自定义的日期格式
public class Magazine {
  private String title;
  private Author authorName;
  private LocalDate localDate;

  @JsonbDateFormat(value = "MM/dd/yyyy", locale = "Locale.ENGLISH")
  public void setLocalDate(LocalDate localDate) {
      this.localDate = localDate;
  }
  // other getter and setters omitted for brevity
}

也可以使用运行时模型来自定义日期格式,如清单 19 所示。在这种情况下,可以在 JsonbConfig 实例上使用 withDateFormat() 方法来设置日期格式和地区。

清单 19. 在 JsonbConfig 实例上设置日期格式
String json = "{\"published\":\"10/10/2018\",
                \"author\":\"Alex Theedom\",
                \"title\":\"Fun with JSON-B\"}";

JsonbConfig jsonbConfig = new JsonbConfig()
    .withDateFormat("MM/dd/yyyy", Locale.ENGLISH);

JsonbBuilder.create(jsonbConfig).fromJson(json, Book.class);

自定义数字格式

可以通过将一个包含特殊数字模式字符的字符串传递给 @JsonbNumberFormat 注解,对数字属性进行显式格式化。清单 20 展示了如何使用模式 "#.00" 格式化一个数字。

清单 20. 定义一个数字字段的数字格式
public class Booklet {
  private String title;
  private Author author;

  @JsonbNumberFormat("#.00")
  private double price;
}

@JsonbNumberFormat 注解可以标记包、类、getter/setter、参数或字段。

请参阅 java.text.DecimalFormat 类的 Javadoc 来获得数字模式格式的详细讨论。

全局运行时自定义

目前讨论的许多自定义可以指定为在字段或方法本地运行,或者在执行的所有操作上全局运行。在下一小节中,您将看到仅有一个全局元素的剩余运行时配置。

自定义二进制数据处理

有 3 种二进制数据处理策略,它们是 BYTEBYTE_64BYTE_64_URL。要自定义二进制数据处理策略,只需向方法 withBinaryDataStrategy() 传递这 3 个静态常量之一,如清单 21 所示。

清单 21. 二进制策略
new JsonbConfig()
  .withBinaryDataStrategy(BinaryDataStrategy.BASE_64_URL);

配置 I-JSON

I-JSON 是一个限制性的 JSON 配置文件,旨在最大限度利用互操作性。默认情况下,JSON-B 与此配置文件大体一致。 在需要确保严格一致性时,可以将 JsonbConfig 实例上的 StrictISON 标志设置为 true 来启用严格一致性。清单 22 显示了如何实现此配置。

清单 22. 设置严格 I-JSON
new JsonbConfig().withStrictIJSON(true);

自定义字符编码

绑定操作将使用此属性指定的编码类型对 JSON 数据进行编码。清单 23 给出了一个示例。

清单 23. 设置默认编码
JsonbConfig jsonbConfig = new JsonbConfig().withEncoding("UTF-32");

RFC 7159 第 8 小节中定义了有效的字符编码。

自定义默认地区

地区可以按清单 24 中所示的方式进行设置。

清单 24. 设置默认 Locale
JsonbConfig jsonbConfig = new JsonbConfig()
  .withLocale(Locale.CANADA);

自定义经过美化的 JSON 输出

可以设置序列化过程的输出,使用合适的换行符和缩进美化 JSON。清单 25 展示了这种配置。

清单 25. 输出经过美化的 JSON
JsonbConfig jsonbConfig = new JsonbConfig().withFormatting(true);

自定义序列化和反序列化

通过目前介绍的简单注解和配置标志,只能实现这么多功能。有时,您需要一种更可靠的、适应性更强的解决方案。JSON-B 的适配器、低级别序列化和反序列化特性就是为这些场景引入的。

JSON-B 适配器

适配器通过实现来自 JsonBAdapter 接口的方法来配置自定义的对象创建和序列化。可以使用 JSON-B 适配器,通过新序列化和反序列化逻辑来覆盖方法 adaptToJson()adaptFromJson()

清单 26 是一个 adaptToJson() 方法实现,包含将 Booklet 对象转换为 JsonObject 的代码。通过使用来自 JSON Processing API 的 JSON Object Builder,adaptFromJson() 方法利用 JsonObject 实例构造了一个 Booklet 对象。

清单 26. JsonbAdapter 接口的实现
public class BookletAdapter implements JsonbAdapter<Booklet, JsonObject> {

  @Override
  public JsonObject adaptToJson(Booklet booklet) {
      return Json.createObjectBuilder()
              .add("title", booklet.getTitle())
              .add("firstName", booklet.getAuthor().getFirstName())
              .add("lastName", booklet.getAuthor().getLastName())
              .build();
  }

  @Override
  public Booklet adaptFromJson(JsonObject json) {
      Booklet booklet = new Booklet(
              json.getString("title"),
              new Author(json.getString("firstName"),
   json.getString("lastName")));
      return booklet;
  }
}

在清单 28 中可以看到,adaptToJson() 方法将 Author 对象“扁平化”为两个属性:firstNamelastName。如清单 27 所示,给定 Booklet 类的一个实例,adaptFromJson() 会重新构造 Author 对象并输出一个 Booklet 实例。

清单 27. Booklet 和 Author 类
public class Booklet {
  	private String title;
  	private Author author;
    // getters and setters omitted for brevity
}

public class Author {
  private String firstName;
  private String lastName;
  // getters and setters omitted for brevity
}

清单 28 给出了输出 Booklet 实例。

清单 28. 一个序列化的 Booklet 对象
{
 "title": "Fun with JSON-B",
 "firstName": "Alex",
 "lastName": "Theedom"
}

使用字段级 JsonbAdapter

JsonbAdapter 非常灵活,可用于自定义各个字段以及整个对象的序列化和反序列化。实现此目标的方法是,使用注解 @JsonbTypeAdapter 来标记应接收自定义行为的字段、方法或类,并向它传递要使用的 JsonbAdapter 的类名。

在清单 29 中,使用 @JsonbTypeAdapter 标记了 firstName 字段,并将 FirstNameAdapter 类指定为适配器。

清单 29. 为 firstName 字段指定 FirstNameAdapter>
public class Author {
  private String lastName;
  @JsonbTypeAdapter(FirstNameAdapter.class)
  private String firstName;
  // getters and setters omitted for brevity
}

清单 30 给出了 FirstNameAdapter 类的实现。

清单 30. FirstNameAdapter 适配器
public class FirstNameAdapter 
implements JsonbAdapter<String, JsonValue> {

  @Override
  public JsonValue adaptToJson(String firstName) {
      return Json.createValue(firstName.subSequence(0,1).toString());
  }

  @Override
  public String adaptFromJson(JsonValue json) {
      return json.toString();
  }
}

适配器类型是根据它应适应一个对象还是字段来确定的。 如果适应一个对象,则使用 JsonObject 类型,如果适应一个字段,则使用 JsonValue 类型。如果字段类型为数组,则使用 JsonArray 类型。

低级别序列化器和反序列化器自定义

JSON-B 序列化器和反序列化器是可用的最低级别自定义,使您能够访问 JSON Processing API 中提供的解析器和生成器。

自定义序列化器必须实现 JsonbSerializer 接口并提供 serialize() 方法的逻辑。清单 31 给出了如何自定义 book 对象的序列化的示例。

清单 31. Book 类的自定义序列化
public class BookSerializer implements JsonbSerializer<Book> {
  @Override
  public void serialize(Book book, JsonGenerator generator, SerializationContext ctx) {
      generator.writeStartObject();
      generator.write("id", "QWE-123-RTS");
      generator.write("title", book.getTitle());
      generator.write("firstName", book.getAuthor().split(" ")[0]);
      generator.write("lastName", book.getAuthor().split(" ")[1]);
      generator.writeEnd();
  }
}

在这个示例中,使用了 JsonGenerator 来逐个属性地创建 JSON 文档。id 属性的值是固定的,作者的姓名扁平化为 firstNamelastName 属性。

通过实现 JsonbDeserializer 接口并提供 deserialize() 方法的逻辑,自定义了反序列化操作。清单 32 中的示例仅从 JSON 文档中提取 Bookid

清单 32. Book 类的自定义反序列化
public class BookDeserializer implements JsonbDeserializer<String> {
  @Override
  public String deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
      while (parser.hasNext()) {
          JsonParser.Event event = parser.next();
          if (event == JsonParser.Event.KEY_NAME) {
              String keyName = parser.getString();
              if (keyName.equals("id")) {
                  return ctx.deserialize(String.class, parser);
              }
          }
          parser.next();
      }
      return "";
  }
}

序列化器和反序列化器的实例通过合适的 withDeserializers()withSerializers() 向一个 JsonbConfig 注册,如清单 33 所示。

清单 33. 注册序列化器和反序列化器
JsonbConfig config = new JsonbConfig()
      .withDeserializers(new BookDeserializer())
      .withSerializers(new BookSerializer());

此外,您还可以使用 @JsonbTypeSerializer@JsonbTypeDeserializer 来注解类型,并传递相关的自定义类的类名。

结束语

JSON-B 的设计者已在着手标准化开发人员在 Java 对象与 JSON 文档之间来回执行转换的方式。如果该 API 和您目前已经学到的特性让您感到似乎有些熟悉,这是特意安排的:该 API 标准化了大部分 Java 开发人员都应该熟悉的序列化和反序列化技术。

两种自定义模型(运行时和编译时)提供了一种高度灵活的、直观的方式来调优该 API。自述性注解和配置方法提高了开发生命周期中的生产力和容易性。借助这些模型,处理更低级别序列化和反序列化操作就和执行高级自定义一样容易。

JSON-B 能从容地处理 Java SE 8 特性(比如 Optional 和新的 Date/Time API),使它领先于艰难应付这些语言构造的其他主要 JSON 解析器。在本系列的下一部分(也是最后一部分),您将亲自了解这一点,届时我将比较 JSON-B 与其他两个非常流行的 JSON 解析器:JacksonGSON

测试您的理解情况

  1. 以下哪些机制可用于自定义默认行为?
    1. 注解包、类、字段和 getter/setter 方法
    2. XML 配置文件
    3. 配置一个 JsonbConfig 实例并将它放在 Jsonb 实例上
    4. 在应用程序启动时引导的属性文件
    5. 一个配置 Singleton
  2. 以下哪些注解是 JSON Binding 注解?
    1. @JsonbProperty
    2. @JsonbIgnore
    3. @JsonbNotNullable
    4. @JsonbPropertyOrder
    5. @JsonbNumberFormat
  3. 以下哪些选项是 JSON Binding 策略?
    1. PropertyVisibilityStrategy
    2. PropertyOrderStrategy
    3. PropertyNamingStrategy
    4. DateAndTimeStrategy
    5. NullPreservationStrategy
  4. 应实现哪个类才能创建自定义适配器?
    1. JsonbCustomAdapter
    2. JsonbSerializationAdapter
    3. JsonbDeserializationAdapter
    4. JsonAdapter
    5. 上述选项都不是
  5. 如何实现并使用 JSON 序列化器?
    1. 实现 JsonbSerializer
    2. 把将要序列化的对象传递给 JsonbSerializer 实例的 serialize() 方法
    3. 为一个 JsonbConfig 实例配置一个 JsonbSerializer 实例
    4. 将一个 JsonbSerializer 实例传递给 @JsonbTypeSerializer
    5. 上述选项都不是

核对您的答案。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=1055459
ArticleTitle=JSON Binding API 入门,第 2 部分: 通过 JSON-B 自定义绑定
publish-date=12142017