JSON-B是用于将Java对象与JSON消息相互转换的标准绑定层。它定义了一种默认的映射算法,用于将现有的Java类转换为JSON,同时使开发人员可以通过使用Java注释自定义映射过程。

安装

座标

Maven依赖

<dependencies>

<!-- JSON-P API -->

<dependency>

<groupId>javax.json</groupId>

<artifactId>javax.json-api</artifactId>

<version>1.1</version>

</dependency>

<!-- JSON-P RI -->

<dependency>

<groupId>org.glassfish</groupId>

<artifactId>javax.json</artifactId>

<version>1.1</version>

<scope>runtime</scope>

</dependency>

<!-- JSON-B API -->

<dependency>

<groupId>javax.json.bind</groupId>

<artifactId>javax.json.bind-api</artifactId>

<version>1.0.0-RC2</version>

</dependency>

<!-- Yasson (JSON-B RI) -->

<dependency>

<groupId>org.eclipse</groupId>

<artifactId>yasson</artifactId>

<version>1.0.0-RC1</version>

<scope>runtime</scope>

</dependency>

</dependencies>

JSON绑定API

默认映射

默认映射是JSON-B引擎默认使用的一组规则,没有提供任何自定义注释和自定义配置。

JSON-B的主要入口点是Jsonb类。它提供了一组重载的toJson和fromJson方法,以将Java对象序列化为JSON文档并反序列化它们。Jsonb实例是线程安全的,可以重用。推荐的方法是每个配置类型具有一个实例。

默认的Jsonb引擎可以这样创建:

Jsonb jsonb = JsonbBuilder.create();

映射对象

下面的示例演示简单POJO的序列化和反序列化。

public class Dog {

public String name;

public int age;

public boolean bitable;

}

// Create a dog instance

Dog dog = new Dog();

dog.name = "Falco";

dog.age = 4;

dog.bitable = false;

// Create Jsonb and serialize

Jsonb jsonb = JsonbBuilder.create();

String result = jsonb.toJson(dog);

// Deserialize back

dog = jsonb.fromJson("{name:\"Falco\",age:4,bitable:false}", Dog.class);

映射集合

JSON-B支持集合和通用集合处理。为了进行适当的反序列化,需要在反序列化期间将所得对象的运行时类型传递给JSON-B。可以按照以下所示的方法来完成。

// List of dogs

List dogs = new ArrayList();

dogs.add(falco);

dogs.add(cassidy);

// Create Jsonb and serialize

Jsonb jsonb = JsonbBuilder.create();

String result = jsonb.toJson(dogs);

// Deserialize back

dogs = jsonb.fromJson(result, ArrayList.getClass());

映射通用集合

JSON-B支持集合和通用集合处理。为了进行适当的反序列化,需要在反序列化期间将所得对象的运行时类型传递给JSON-B。可以按照以下所示的方法来完成。

// List of dogs

List<Dog> dogs = new ArrayList<>();

dogs.add(falco);

dogs.add(cassidy);

// Create Jsonb and serialize

Jsonb jsonb = JsonbBuilder.create();

String result = jsonb.toJson(dogs);

// Deserialize back

dogs = jsonb.fromJson(result, new ArrayList<Dog>(){}.getClass().getGenericSuperclass());

定制映射

您可以通过许多不同的方式自定义映射。您可以将JSON-B批注用于编译时定制,而可以将JsonbConfig类用于运行时定制。

以下示例显示了如何使用自定义配置创建JSON-B引擎:

// Create custom configuration

JsonbConfig config = new JsonbConfig();

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

格式化输出

// Create custom configuration with formatted output

JsonbConfig config = new JsonbConfig()

.withFormatting(true);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

// Use it!

String result = jsonb.toJson(pojo);

更改属性名称

默认情况下,JSON属性名称与Java属性名称相同。一个常见的用例是使用不同的名称序列化属性。这可以通过在字段上使用@JsonbProperty注释来实现,也可以使用JsonbNamingStrategy全局地实现。

@JsonbProperty批注

@JsonbProperty用于更改一个特定属性的名称。可以放置

  • 现场,在这种情况下会影响序列化和反序列化
  • 在吸气剂上,在这种情况下,它将仅影响序列化
  • 在setter上,在这种情况下,它将仅影响反序列化

在下面的示例属性中,属性名称将被序列化为“ person-name”。

public class Person {

@JsonbProperty("person-name")

private String name;

private String profession;

}

生成的JSON文档将如下所示:

{

"person-name": "Jason Bourne",

"profession": "Super Agent"

}

如果将@JsonbProperty批注放在getter上,将生成相同的JSON文档,如下所示:

public class Person {

private String name;

private String profession;

@JsonbProperty("person-name")

public String getName() {

return name;

}

}

此示例演示了将属性写入一个JSON属性并从另一个属性读取的能力。属性'name'被序列化为'name-to-write'属性,并在反序列化期间从'name-to-read'属性读取。

public class Person {

private String name;

private String profession;

@JsonbProperty("name-to-write")

public String getName() {

return name;

}

@JsonbProperty("name-to-read")

public void setName(String name) {

this.name = name;

}

}

命名策略

命名策略用于更改构造属性名称的默认方式。

支持的命名策略是:

  • 身份(myMixedCaseProperty)
  • LOWER_CASE_WITH_DASHES(我的混合案例属性)
  • LOWER_CASE_WITH_UNDERSCORES(my_mixed_case_property)
  • UPPER_CAMEL_CASE(MyMixedCaseProperty)
  • UPPER_CAMEL_CASE_WITH_SPACES(我的混合大小写财产)
  • CASE_INSENSITIVE(mYmIxEdCaSePrOpErTy)
  • 或您的JsonbNamingStrategy接口的自定义实现

IDENTITY策略是默认策略。

可以与JsonbConfig类的withPropertyNamingStrategy方法一起使用:

// Custom configuration

JsonbConfig config = new JsonbConfig()

.withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_DASHES);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

...

属性顺序

为了自定义序列化属性的顺序,JSON Binding提供了PropertyOrderStrategy类。

支持的策略是:

  • 词汇(AZ)
  • ANY(顺序未定义,在大多数情况下,顺序将在类中显示属性)
  • 倒车(ZA)

默认订购策略为LEXICOGRAPHICAL。可以使用JsonbConfig类的withPropertyOrderStrategyy方法全局应用订购策略:

// Custom configuration

JsonbConfig config = new JsonbConfig()

.withPropertyOrderStrategy(PropertyOrderStrategy.ANY);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

...

或在类上使用@JsonbPropertyOrder批注:

@JsonbPropertyOrder(PropertyOrderStrategy.ANY)

public class Person {

private String name;

private String profession;

}

忽略属性

使用@JsonbTransient注释注释的类属性将被JSON绑定引擎忽略。行为因@JsonbTransient批注的放置位置而异。

  • 现场:在序列化和反序列化期间,将忽略属性。
  • 在getter上:仅在序列化期间忽略属性。
  • 在setter上:仅在反序列化期间忽略属性。

此类的序列化

@JsonbPropertyOrder(PropertyOrderStrategy.ANY)

public class Person {

@JsonbTransient

private String name;

private String profession;

}

将产生以下JSON文档:

{

"profession": "Super Agent"

}

如果将@JsonbTransient批注这样放置在getter上:

public class Person {

private String name;

private String profession;

@JsonbTransient

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

'name'属性不会被序列化,但是会被反序列化。

空处理

默认情况下,JSON-B不会序列化具有空值的字段。这可能是不希望的行为。有三种不同的方法可以更改默认的空值处理。

  • 在类或包级别使用@JsonbNillable批注

@JsonbNillable

public class Person {

private String name;

private String profession;

}

  • 在使用@JsonbProperty批注和nillable = true参数的单个属性上

public class Person {

@JsonbProperty(nillable=true)

private String name;

private String profession;

}

  • 全局使用JsonbConfig类的withNullValues方法

// Create custom configuration

JsonbConfig nillableConfig = new JsonbConfig()

.withNullValues(true);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(nillableConfig);

...

自定义实例

默认情况下,反序列化需要使用公共默认的无参数构造函数。在许多情况下,此要求过于严格。JSON-B提供@JsonbCreator批注,可用于使用参数或用于创建类实例的静态工厂方法对自定义构造函数进行批注。

下面的示例显示了如何在自定义构造函数上使用@JsonbCreator批注。必须使用构造函数参数上的@JsonbProperty批注来正确替换参数。在这种情况下,会将JSON属性“名称”的值传递给构造函数。

public class Person {

private String name;

private String profession;

@JsonbCreator

public Person(@JsonbProperty("name") String name) {

this.name = name;

}

}

日期/数字格式

默认情况下,JSON-B使用ISO格式对日期和数字字段进行序列化和反序列化。有时需要覆盖这些设置。可以在字段上使用@JsonbDateFormat和@JsonbNumberFormat批注来完成:

public class Person {

public String name;

@JsonbDateFormat("dd.MM.yyyy")

private Date birthDate;

@JsonbNumberFormat(“#0.00")

public BigDecimal salary;

}

或全局使用JsonbConfig类的withDateFormat方法:

// Create custom configuration

JsonbConfig config = new JsonbConfig()

.withDateFormat("dd.MM.yyyy", null);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

...

二进制编码

JSON-B支持二进制数据的映射。默认情况下,它使用BYTE编码,但是可以使用BinaryDataStrategy类轻松对其进行自定义,该类提供对最常见的二进制数据编码的支持:

  • 字节
  • BASE_64
  • BASE_64_URL

以下示例显示了使用BASE_64_URL编码的Jsonb引擎的创建:

// Create custom configuration

JsonbConfig config = new JsonbConfig()

.withBinaryDataStrategy(BinaryDataStrategy.BASE_64);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

...

转接器

在某些情况下,可能很难以所需方式对类进行序列化/反序列化。有时无法在源代码上放置自定义注释,因为您无权访问它,或者自定义注释不能解决问题。在这种情况下,可以尝试使用适配器。

Adapter是一个实现javax.json.bind.adapter.JsonbAdapter接口的类。它具有一个自定义代码,可将“不可映射”类型(原始)转换为所需方式序列化/反序列化的另一种(“自适应”)。嘲讽JAXB中的类型适配器如何工作。

让我们看一下示例。假设您有一个包含所有客户详细信息的Customer对象。在一种情况下,您需要序列化整个对象,在另一种情况下,您仅需要提供其ID和名称。解决方案可能是将其序列化为第一种情况,并为JsonObject创建一个适配器,该适配器仅包含第二种情况所需的数据。

public class Customer {

private int id;

private String name;

private String organization;

private String position;

...

}

public class CustomerAdapter implements JsonbAdapter<Customer, JsonObject> {

@Override

public JsonObject adaptToJson(Customer c) throws Exception {

return Json.createObjectBuilder()

.add("id", c.getId())

.add("name", c.getName())

.build();

}

@Override

public Customer adaptFromJson(JsonObject adapted) throws Exception {

Customer c = new Customer();

c.setId(adapted.getInt("id"));

c.setName(adapted.getString("name"));

return c;

}

}

第一种情况:

// Create Jsonb with default configuration

Jsonb jsonb = JsonbBuilder.create();

// Create customer

Customer c = new Customer();

// Initialization code is skipped

// Serialize

jsonb.toJson(customer);

结果:

{

"id": 1,

"name": "Json Bourne",

"organization": "Super Agents",

"position": "Super Agent"

}

第二种情况:

// Create custom configuration

JsonbConfig config = new JsonbConfig()

.withAdapters(new CustomerAdapter());

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

// Create customer

Customer c = new Customer();

// Initialization code is skipped

// Serialize

jsonb.toJson(customer);

结果:

{

"id": 1,

"name": "Json Bourne"

}

序列化器/反序列化器

有时,适配器机制还不够,因此需要对JSONP解析器/生成器的低级别访问。

从规格:

Serializer是一个实现javax.json.bind.serializers.JsonbSerializer接口的类。它用于序列化其在(原始)上注册的类型。在对原始类型进行序列化时,JSONB调用JsonbSerializer :: serialize方法。此方法必须包含一个自定义代码,才能使用提供的JsonpGenerator序列化Original类型。

Deserializer是实现javax.json.bind.serializers.JsonbDeserializer接口的类。它用于反序列化其在(原始)上注册的类型。在对原始类型进行反序列化时,JSONB调用JsonbDeserializer :: deserialize方法。此方法必须包含一个自定义代码,以使用提供的JsonpParser反序列化Original类型。

让我们看一下示例。想象一下,我们想序列化和反序列化宠物载体列表。由抽象类Animal定义的宠物。它可以是其任何子类。我们想适当地序列化和反序列化它。为此,我们需要在JSON文档中保留类型信息,并在反序列化时使用它。可以使用自定义的串行器/解串器对来完成。

模型:

public abstract class Animal {

private String name;

private int age;

private Boolean furry;

...

}

public class Cat extends Animal {

private Boolean cuddly;

...

}

public class Dog extends Animal {

private Boolean barking;

...

}

public class Carrier<P extends Pet> {

public enum TYPE {

BAG, CRATE, TROLLEY

}

private TYPE carrierType;

private P carriedPet;

@JsonbCreator

public Carrier(TYPE carrierType, A carriedPet) {

this.carrierType = carrierType;

this.carriedPet = carriedPet;

}

...

}

序列化器/解串器:

public class AnimalSerializer implements JsonbSerializer<Animal> {

public void serialize(Animal animal, JsonGenerator jsonGenerator, SerializationContext serializationContext) {

if (animal != null) {

serializationContext.serialize(animal.getClass().getName(), animal, jsonGenerator);

} else {

serializationContext.serialize(null, jsonGenerator);

}

}

}

public class AnimalDeserializer implements JsonbDeserializer<Animal> {

public Animal deserialize(JsonParser jsonParser, DeserializationContext deserializationContext, Type type) {

Animal animal = null;

while (jsonParser.hasNext()) {

JsonParser.Event event = jsonParser.next();

if (event == JsonParser.Event.KEY_NAME) {

String className = jsonParser.getString();

jsonParser.next();

try {

animal = deserializationContext.deserialize(Class.forName(className).asSubclass(Animal.class), jsonParser);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

return animal;

}

}

用法:

// Create a list of carrier objects

List<Carrier<Pet>> carriers = new ArrayList<>();

carriers.add(new Carrier<>(Carrier.TYPE.BAG, new Cat("Harris", 10, true, true)));

carriers.add(new Carrier<>(Carrier.TYPE.CRATE, new Dog("Falco", 4, false, false)));

Type carrierListType = new ArrayList<Carrier<Pet>>() {}.getClass().getGenericSuperclass();

JsonbConfig config = new JsonbConfig()

.withFormatting(true)

.withSerializers(new PetSerializer())

.withDeserializers(new PetDeserializer());

Jsonb jsonb = JsonbBuilder.create(config);

String json = jsonb.toJson(carriers, carrierListType);

System.out.println(json);

List<Carrier<Pet>> list = jsonb.fromJson(json, carrierListType);

System.out.println(list.get(0).getCarriedPet().getClass().getName());

严格的I-JSON支持

I-JSON(“ Internet JSON”)是JSON的受限配置文件。JSON-B默认情况下完全支持I-JSON,但有以下三个例外:

  • JSON绑定不限制既不是对象也不是数组的顶级JSON文本的序列化。该限制应发生在应用程序级别。
  • JSON绑定不会使用base64url编码序列化二进制数据。
  • JSON绑定不会对日期/时间/持续时间实施其他限制。

可以如下所示打开完全支持模式:

// Create custom configuration

JsonbConfig config = new JsonbConfig()

.withStrictIJSON(true);

// Create Jsonb with custom configuration

Jsonb jsonb = JsonbBuilder.create(config);

...

更多的信息

  • JSON-B官方网站:http : //json-b.net
  • 规范项目:http://github.com/javaee/jsonb-spec
  • JCP网站上的JSR-367页面:https : //jcp.org/en/jsr/detail? id = 367
  • Yasson(参考实现):https ://projects.eclipse.org/projects/rt.yasson

最后更新2017-06-09 17:57:04 CEST

Java Json Binding JSON-B使用示例相关推荐

  1. Java秘技之Json数据解析与转换 -- Java使用示例

    概要 json是前后台交互常用的数据格式,在java后台中经常需要实现java bean.list和json字符串的相互转化,故简单介绍不同框架的使用,提供简单工具类. 在Java中,常见的json框 ...

  2. java+解析未知json_在Java中解析JSON时如何忽略未知属性– Jackson @JsonIgnoreProperties注释示例...

    java+解析未知json 使用Jackson API在Java中解析JSON时的常见问题之一是,当您的JSON包含未知属性(即您的Java类没有对应于所有JSON属性的所有字段)时,该操作将失败. ...

  3. java 如何导出json文件_java导出json格式文件的示例代码

    本文介绍了java导出json格式文件的示例代码,分享给大家,具体如下: import java.io.File; import java.io.FileWriter; import java.io. ...

  4. IDEA Java解析GeoJson.json文件

    IDEA Java解析GeoJson.json文件 一.遇到的问题 1. 无法导入成功 2. org.geotools.StyleFactory is not an ImageIO SPI class ...

  5. java如何读写json文件

    java如何读写json文件 在实际项目开发中,有时会遇到一些全局的配置缓存,最好的做法是配置redis数据库作为数据缓存,而当未有配置redis服务器时,读取静态资源文件(如xml.json等)也是 ...

  6. java gson 工具类_gson工具类将Java类转换为json的使用

    示例如何将一个 Student 对象转换成 json 串,实际操作中我们也可以将任意的 Java 类转换为 json 串,并且实施起来也非常简单,你仅仅需要创建一个 Gson 实例,然后传递将被转化为 ...

  7. java 视图对象转换,使用spring boot开发时java对象和Json对象转换的问题_JavaScript_网络编程...

    将java对象转换为on对象,市面上有很多第三方jar包,如下: jackson(最常用) com.fasterxml.jackson.core jackson-databind 2.11.2 gso ...

  8. json java 实例_java JSON数据转对象

    只要电脑配置了JDK, 便可使用Json2Bean, 不用导入到eclipse或android studio, 直接双击就可以打开使用, 每次使用之前要重新设置编辑规则,不用改动什么规则,点" ...

  9. 码这么多字只为搞懂如何在Python和Java中使用JSON

    目录 1 JSON是什么? 1.1 JSON是众多编程语言共同的"简谱" 1.2 JSON是一种高度结构化的文本 2 如何在Python中使用JSON 2.1 内置库json的编码 ...

最新文章

  1. win10搭建python环境_win10系统搭建python环境的还原方法
  2. html的meta用法
  3. Linux 驱动编译报错:error: macro __DATE__ might prevent reproducible builds [-Werror=date-time]
  4. swift使用mysql教程,Swift学习教程之SQLite的基础使用
  5. laravel 自带的用户登录视图路径_Laravel实现找回密码及密码重置,详细操作
  6. 【HISI系列】之IP/MAC地址配置
  7. 大数据分析有几种方法
  8. 2019美赛D题,元胞自动机模拟游客疏散过程
  9. [常用办公软件] wps怎么自动生成目录?wps自动生成目录的设置教程
  10. excel打开密码忘记了_Excel工作表保护密码忘记了怎么办?这一招轻松去除密码...
  11. 基于某电信运营数据的精准营销分析
  12. 教程:使用tensorflow-slim训练自己数据的图像分类器
  13. 小马哥-----高仿米4拆机 刷机主板多图展示 主板为x77 型号k6 6582芯片 14年底版本
  14. android 跳转第三方应用qq或联系我们功能使用qq
  15. 2020年全球高被引科学家名单出炉!内地770人上榜
  16. GitStats - 统计Git所有提交记录工具
  17. php 新闻分页,php原生开发新闻站之新闻列表分页
  18. 智能公交系统出行越来越便捷
  19. 如何创建属于自己的脚手架
  20. Android 实时采集声音的频率和大小

热门文章

  1. 【置顶】所有汇总帖地址
  2. 步进电机S曲线加减速控制生成器-VB6.0实现
  3. C++ 不定参宏展开
  4. LGPL许可协议具体限制了什么?
  5. 计算机网络概念入门(十一)
  6. h5页面下载apk方法
  7. 基于4G网卡的Telnet远程登录RT-Thread的Finsh/MSH Shell
  8. android+直播点赞,Android自定义View实现直播点赞特效的方法
  9. 使用开源软件和Tectonic,摆脱云服务供应商的锁定
  10. div隐藏(设置div隐藏)