jackson最新使用手册

概述

jackson包含Jackson Data Processor的通用数据绑定功能和树模型。它建立在Streaming API(流解析器/生成器)包之上,并使用Jackson Annotations进行配置。项目在Apache License 2.0下获得许可。虽然Jackson的原始用例是JSON数据绑定,但只要存在解析器和生成器实现,它现在也可以用于读取以其他数据格式编码的内容。类的命名在很多地方都使用了“JSON”这个词,尽管对JSON格式并没有实际的硬性依赖。

Maven

这个包的功能包含在Java包com.fasterxml.jackson中。可以使用以下Maven依赖项

<dependencies>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.14.2</version>
  </dependency>
</dependencies>

这个包依赖于jackson-core和jackson-annotations包,但是当使用像Maven或Gradle这样的构建工具时,依赖项会自动包含在内。如果不使用Maven或Gradle这样的构建工具可以使用项目的pom.xml处理依赖关系的构建工具,则需要下载并显式包含这两个jar。

兼容性

JDK Jackson-databind包基线JDK需求如下:

  • 版本2.0 - 2.7需要JDK6
  • 版本2.8 - 2.12需要JDK7
  • 运行(但2.11 - 2.12需要JDK 8构建)2.13及以上版本需要JDK8

POJO到JSON和JSON到POJO

// Note: can use getters/setters as well; here we just use public fields directly:
public class MyValue {
  public String name;
  public int age;
  // NOTE: if using getters/setters, can keep fields `protected` or `private`
}

我们将需要一个com.fasterxml.jackson.databind.ObjectMapper实例,用于所有数据绑定

ObjectMapper mapper = new ObjectMapper(); // create once, reuse
MyValue value = mapper.readValue(new File("data.json"), MyValue.class);
value = mapper.readValue(new URL("http://some.com/api/entry.json"), MyValue.class);
value = mapper.readValue("{"name":"Bob", "age":13}", MyValue.class);

如果我们想写JSON,我们做相反的

ObjectMapper mapper = new ObjectMapper(); // create once, reuse
mapper.writeValue(new File("result.json"), myResultObject);
byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject);
String jsonString = mapper.writeValueAsString(myResultObject);

除了处理简单的bean风格的pojo,你还可以处理JDK的列表、映射:

ObjectMapper mapper = new ObjectMapper(); // create once, reuse
Map<String, Integer> scoreByName = mapper.readValue(jsonSource, Map.class);
List<String> names = mapper.readValue(jsonSource, List.class);
// and can obviously write out as well
mapper.writeValue(new File("names.json"), names);

虽然处理映射、列表和其他“简单”对象类型(字符串、数字、布尔值)可能很简单,但对象遍历可能很麻烦。这就是Jackson的树模型可以派上用场的地方:

ObjectMapper mapper = new ObjectMapper(); // create once, reuse
ObjectNode root = mapper.readTree("stuff.json");
String name = root.get("name").asText();
int age = root.get("age").asInt();

// 这将添加子对象作为属性'other',设置属性'type'
root.with("other").put("type", "student");
String json = mapper.writeValueAsString(root);
/*
使用上面的代码,我们最终得到类似于'json'字符串的东西:
{
    "name" : "Bob",
    "age" : 13,
    "other" : {
        "type" : "student"
    }
} 
*/

流 解析器、生成器

尽可能方便地进行数据绑定(到/从pojo);尽管树模型非常灵活,但还有一种更规范的处理模型可用:增量(又名“流”)模型。它是数据绑定和树模型所构建的底层处理模型,但它也暴露给那些希望获得最终性能和/或控制解析或生成细节的用户。要了解更深入的解释,请查看Jackson Core组件。

ObjectMapper mapper = ...;
// 首先:编写简单的JSON输出
File jsonFile = new File("test.json");
// 注意:在Jackson 2.11中添加的方法(以前需要使用)
// mapper.getFactory () .createGenerator(…)
JsonGenerator g = f.createGenerator(jsonFile, JsonEncoding.UTF8);
// write JSON: { "message" : "Hello world!" }
g.writeStartObject();
g.writeStringField("message", "Hello world!");
g.writeEndObject();
g.close();
// 第二:回读文件
try (JsonParser p = mapper.createParser(jsonFile)) {
  JsonToken t = p.nextToken(); // Should be JsonToken.START_OBJECT
  t = p.nextToken(); // JsonToken.FIELD_NAME
  if ((t != JsonToken.FIELD_NAME) || !"message".equals(p.getCurrentName())) {
   // handle error
  }
  t = p.nextToken();
  if (t != JsonToken.VALUE_STRING) {
   // similarly
  }
  String msg = p.getText();
  System.out.printf("My message to you is: %s!\n", msg);
}

配置

您可能会使用两种入门级配置机制:特性和注解。

// SerializationFeature改变JSON的写入方式
//启用标准缩进("pretty-printing"):
mapper.enable(SerializationFeature.INDENT_OUTPUT);
//允许“空”pojo的序列化(没有属性可以序列化)
//(没有此设置,在这些情况下抛出异常)
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//编写java.util。日期,日历作为数字(时间戳):
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// DeserializationFeature改变JSON作为pojo的读取方式:
//当遇到未知属性时防止出现异常:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//允许将JSON空字符串("")强制转换为null对象值:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

此外,您可能需要更改一些低级JSON解析,生成细节:

// JsonParser。配置解析设置的功能:
//允许在JSON中使用C/ c++风格的注释(非标准,默认禁用)
//(注意:在Jackson 2.5中,还有' mapper.enable(feature) ' / ' mapper.disable(feature) ')
mapper.configure (JsonParser.Feature。ALLOW_COMMENTS,true);
//在JSON中允许(非标准的)未加引号的字段名:
mapper.configure (JsonParser.Feature。ALLOW_UNQUOTED_FIELD_NAMES,true);
//允许使用撇号(单引号),非标准
mapper.configure (JsonParser.Feature。ALLOW_SINGLE_QUOTES,true);
// JsonGenerator。配置低级JSON生成的特性:
//强制转义非ascii字符:
mapper.configure (JsonGenerator.Feature。ESCAPE_NON_ASCII,true);

在Jackson功能页面上解释了全套功能。

注释:更改属性名称
最简单的基于注解的方法是像这样使用@JsonProperty注解:
public class MyBean {
    @JsonProperty("name")
    private String _name;
}


有两种主要的注释可以用来忽略属性:
@JsonIgnore用于单个属性;
@JsonIgnoreProperties用于每个类的定义
@JsonIgnoreProperties({ "foo", "bar" })
public class MyBean{
   //不会写入JSON;也不是从JSON分配的:
   @JsonIgnore
   public String internal;
   //无标注,公共字段正常读写
   public String external;
}

更花哨的东西,转换

Jackson的一个有用(但并不广为人知)的特性是它能够进行任意pojo到pojo的转换。从概念上讲,您可以将转换视为两个步骤的序列:首先,将POJO写入JSON,然后将JSON绑定到另一种POJO。实现只是跳过实际的JSON生成,并使用更有效的中间表示。

转换可以在任何兼容类型之间工作,调用就像这样简单:

ResultType result = mapper.convertValue(sourceObject, ResultType.class);

只要源和结果类型是兼容的——也就是说,如果to-JSON和from-JSON序列可以成功——事情就会“正常工作”。但这里有几个潜在的有用用例:

//将List<Integer>转换为int[]
List<Integer> sourceList = ...;
int[] ints = mapper.convertValue(sourceList, int[].class);
//将POJO转换为Map!
Map<String,Object> propertyMap = mapper.convertValue(pojoValue, Map.class);
// ... and back
PojoType pojo = mapper.convertValue(propertyMap, PojoType.class);
//Base64解码!(默认的byte[]表示是base64编码的String)
String base64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz";
byte[] binary = mapper.convertValue(base64, byte[].class);
//基本上,Jackson可以作为许多Apache Commons组件的替代品
    //用于base64编码/解码和处理“动态bean”(映射到pojo /从pojo)等任务。

教程:Builder设计模式+ Jackson

Builder设计模式是一种创建性设计模式,可用于逐步创建复杂对象。如果我们有一个对象需要对其他依赖项进行多次检查,在这种情况下,最好使用构建器设计模式。

让我们考虑person结构,它有一些可选字段

public class Person {
    private final String name;
    private final Integer age;
 
    // getters
}

让我们看看如何在反序列化中使用它的功能。首先,让我们声明一个私有的全参数构造函数和一个Builder类。

private Person(String name, Integer age) {
    this.name = name;
    this.age = age;
}
static class Builder {
    String name;
    Integer age;
    Builder withName(String name) {
        this.name = name;
        return this;
    }
    Builder withAge(Integer age) {
        this.age = age;
        return this;
    }
    public Person build() {
        return new Person(name, age);
    } 
}

首先,我们需要用@JsonDeserialize注释标记我们的类,传递一个带有构建器类的完全限定域名的构建器参数。之后,我们需要将构建器类本身注释为@JsonPOJOBuilder。

@JsonDeserialize(builder = Person.Builder.class)
public class Person {
    //...
    
    @JsonPOJOBuilder
    static class Builder {
        //...
    }
}

一个简单的单元测试是:

String json = "{"name":"Hassan","age":23}";
Person person = new ObjectMapper().readValue(json, Person.class);
 
assertEquals("Hassan", person.getName());
assertEquals(23, person.getAge().intValue());

如果您的构建器模式实现为方法使用了其他前缀,或者为构建器方法使用了build()以外的其他名称,Jackson还为您提供了一种方便的方法。
例如,如果你有一个构建器类,它的方法使用“set”前缀,并使用create()方法而不是build()来构建整个类,你必须这样注释你的类:

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
static class Builder {
    String name;
    Integer age;
    Builder setName(String name) {
        this.name = name;
        return this;
    }
    Builder setAge(Integer age) {
        this.age = age;
        return this;
    }
    public Person create() {
        return new Person(name, age);
    } 
}

要以不同于对象对应的名称反序列化JSON字段,可以在构建器中对相应字段使用@JsonProperty注释。

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
static class Builder {
    @JsonProperty("known_as")
    String name;
    Integer age;
    //...
}

这将把JSON属性n_as反序列化为构建器字段名。如果没有提供这样的映射(并且没有提供进一步的注释来处理此问题),如果在反序列化期间提供了该字段,则将抛出一个未识别字段“known_as”异常。
如果您希望引用具有多个别名的属性进行反序列化,可以使用@JsonAlias注释。

@JsonPOJOBuilder(buildMethodName = "create", withPrefix = "set")
static class Builder {
    @JsonProperty("known_as")
    @JsonAlias({"identifier", "first_name"})
    String name;
    Integer age;
    //...
}

这将使用known_as以及标识符和first_name将JSON字段反序列化为name。可以通过指定一个字符串作为JsonAlias(“标识符”)来使用单个别名,而不是一个条目数组。
注意:要使用@JsonAlias注释,还必须使用@JsonProperty注释。
总的来说,Jackson库在使用构建器模式反序列化对象方面非常强大。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

撸码仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值