Jackson数据处理及绑定
Posted fighting-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jackson数据处理及绑定相关的知识,希望对你有一定的参考价值。
获取
Maven的
该软件包的功能包含在Java包中com.fasterxml.jackson.databind
,可以使用以下Maven依赖项来使用:
< properties >
...
<! -尽可能使用最新版本。- >
< jackson .version> 2.9.7 </ jackson .version>
...
</ properties >
< dependencies >
...
< 依赖 >
< groupId > com.fasterxml.jackson.core </ groupId >
< artifactId > jackson-databind </ artifactId >
< version > $ {jackson.version} </ version >
</ dependency >
...
</ dependencies >
由于包依赖于包jackson-core
和jackson-annotations
包,因此如果不使用Maven,则需要下载这些包; 并且您可能还希望将它们添加为Maven依赖项以确保使用兼容版本。如果是这样,还要添加:
< dependencies >
...
< dependency >
<! -注意:core-annotations版本xy0通常与
版本xy1,xy2等兼容(相同)- >
< groupId > com.fasterxml.jackson.core </ groupId >
< artifactId > jackson-annotations </ artifactId >
< version > $ {jackson.version} </ version >
</ dependency >
< 依赖 >
< groupId > com.fasterxml.jackson.core </ groupId >
< artifactId > jackson-core </ artifactId >
< version > $ {jackson.version} </ version >
</ dependency >
...
< dependencies >
但请注意,这是可选的,只有在jackson核心依赖关系通过传递依赖关系存在冲突时才有必要。
非Maven的
对于非Maven用例,您可以从Central Maven存储库下载jar 。
Databind jar也是一个功能性的OSGi包,具有适当的导入/导出声明,因此它可以在OSGi容器上使用。
使用
可以从Jackson-docs存储库中找到更全面的文档; 以及来自此项目的Wiki。但这里有简要的介绍性教程,建议阅读顺序。
1分钟教程:POJO到JSON并返回
最常见的用法是使用JSON,并从中构造一个Plain Old Java Object(“POJO”)。那么让我们从那里开始。简单的2属性POJO像这样:
//注意:也可以使用getter / setter; 这里我们直接使用公共字段:
public class MyValue {
public String name;
公共 INT年龄;
//注意:如果使用getter / setter,可以保留字段`protected`或`private`
}
我们需要一个com.fasterxml.jackson.databind.ObjectMapper
用于所有数据绑定的实例,所以让我们构造一个:
ObjectMapper mapper = new ObjectMapper(); //创建一次,重用
默认实例适合我们使用 - 稍后我们将了解如何在必要时配置映射器实例。用法很简单:
MyValue value = mapper.readValue(new File("data.json"), MyValue.class);
// or:
value = mapper.readValue(new URL("http://some.com/api/entry.json"), MyValue.class);
// or:
value = mapper.readValue("{"name":"Bob", "age":13}", MyValue.class);
如果我们想写JSON,我们会反过来:
mapper.writeValue(new File("result.json"), myResultObject);
// or:
byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject);
// or:
String jsonString = mapper.writeValueAsString(myResultObject);
到现在为止还挺好?
3分钟教程:通用集合,树模型
除了处理简单的Bean风格的POJO之外,您还可以处理JDK List
,Map
s:
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);
只要JSON结构匹配,类型就很简单。如果您有POJO值,则需要指明实际类型(注意:对于具有List
etc类型的POJO属性,这不是必需的):
Map<String, ResultValue> results = mapper.readValue(jsonSource,
new TypeReference<Map<String, ResultValue>>() { } );
// why extra work? Java Type Erasure will prevent type detection otherwise
(注意:无论通用类型如何,序列化都不需要额外的工作)
可是等等!还有更多!
虽然处理Map
s,List
s和其他“简单”对象类型(字符串,数字,布尔值)可能很简单,但对象遍历可能很麻烦。这就是Jackson‘s Tree模型可以派上用场的地方:
//可以读作通用的JsonNode,如果它可以是Object或Array; 或者,
//如果已知为Object,则为ObjectNode,如果是array,ArrayNode等:
ObjectNode root = mapper.readTree("stuff.json");
String name = root.get("name").asText();
int age = root.get("age").asInt();
//也可以修改:这会将子对象添加为属性‘other‘,设置属性‘root.with("other").put("type", "student");
String json = mapper.writeValueAsString(root);
//与上面一样,我们最终得到像‘json‘字符串:// {
// "name" : "Bob", "age" : 13,
// "other" : {
// "type" : "student"
// }
// }
树模型比数据绑定更方便,特别是在结构高度动态或不能很好地映射到Java类的情况下。
5分钟教程:流解析器,生成器
数据绑定(往/来自POJO)可以方便; 并且像Tree模型一样灵活,还有一个可用的规范处理模型:增量(又称“流”)模型。它是数据绑定和树模型都构建的底层处理模型,但它也向需要最终性能和/或控制解析或生成细节的用户公开。
有关深入解释,请查看Jackson Core组件。但是,让我们看一个简单的预告片,以激发你的胃口。
JsonFactory f = mapper.getFactory(); // may alternatively construct directly too
// First: write simple JSON output
File jsonFile = new File("test.json");
JsonGenerator g = f.createGenerator(jsonFile);
// write JSON: { "message" : "Hello world!" }
g.writeStartObject();
g.writeStringField("message", "Hello world!");
g.writeEndObject();
g.close();
// Second: read file back
JsonParser p = f.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!
", msg);
p.close();
10分钟教程:配置
常用功能
以下是您最有可能需要了解的配置功能示例。
让我们从更高级别的数据绑定配置开始。
// SerializationFeature用于更改JSON的编写方式
//启用标准缩进(“漂亮打印”):mapper.enable(SerializationFeature.INDENT_OUTPUT);
//允许序列化“空”POJO(没有要序列化的属性)
//(没有这个设置,在这些情况下抛出异常)mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//编写java.util.Date,Calendar as number(timestamp):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.Feature:
//允许JSON中的C / C ++样式注释(非标准,默认禁用)
//(注意:使用Jackson 2.5,还有`mapper.enable(feature)`/`mapper.disable(feature)`)mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
//允许在JSON:
mapper中允许(非标准)不带引号的字段名称。配置( JsonParser 。功能。 ALLOW_UNQUOTED_FIELD_NAMES,真);
//允许使用撇号(单引号),非标准mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
//用于配置低级JSON生成的JsonGenerator.Feature:
//强制转义非ASCII字符:
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
注释:更改属性名称
最简单的基于注释的方法是使用如下@JsonProperty
注释:
public class MyBean {
private String _name;
//没有注释,我们得到“theName”,但我们想要“name”:
@JsonProperty("name")
public String getTheName() { return _name; }
//注意:只需在getter或setter上添加注释即可;
//所以我们可以省略它
public void setTheName(String n) { _name = n; }
}
还有其他机制可用于系统命名更改:有关详细信息,请参阅自定义命名约定。
另请注意,您可以使用“ 混合注释”来关联所有注释。
注释:忽略属性
有两个主要注释可用于忽略属性:@JsonIgnore
对于单个属性; 并@JsonIgnoreProperties
为每班定义
//意味着如果我们在JSON中看到“foo”或“bar”,它们将被静静地跳过
//无论POJO是否具有这样的属性
@JsonIgnoreProperties({ "foo", "bar" })
public class MyBean
{
// will not be written as JSON; nor assigned from JSON:
@JsonIgnore
public String internal;
// no annotation, public field is read/written normally
public String external;
@JsonIgnore
public void setCode(int c) { _code = c; }
// note: will also be ignored because setter has annotation!
public int getCode() { return _code; }
}
与重命名一样,请注意注释在匹配字段,getter和setter之间“共享”:如果只有一个@JsonIgnore
,则会影响其他字段。但也可以使用“拆分”注释,例如:
public class ReadButDontWriteProps {
private String _name;
@JsonProperty public void setName(String n){_ name = n; }
@JsonIgnore public String getName(){ return _name; }
}
在这种情况下,不会写出“name”属性(因为‘getter‘被忽略); 但如果从JSON中找到“name”属性,它将被分配给POJO属性!
有关在写出JSON时忽略属性的所有可能方法的更完整说明,请选中“过滤属性”一文。
注释:使用自定义构造函数
与许多其他数据绑定包不同,Jackson不要求您定义“默认构造函数”(不带参数的构造函数)。虽然它将使用一个,如果没有其他可用,您可以轻松定义使用参数构造函数:
public class CtorBean
{
public final String name;
public final int age;
@JsonCreator // constructor can be public, private, whatever
private CtorBean(@JsonProperty("name") String name,
@JsonProperty("age") int age)
{
this.name = name;
this.age = age;
}
}
构造函数在支持使用Immutable对象方面特别有用 。
或者,您也可以定义“工厂方法”:
public class FactoryBean
{
// fields etc omitted for brewity
@JsonCreator
public static FactoryBean create(@JsonProperty("name") String name) {
// construct and return an instance
}
}
请注意,使用“创建者方法”(@JsonCreator
带有@JsonProperty
注释参数)并不排除使用setter:您可以将构造函数/工厂方法中的属性与通过setter设置的属性或直接使用字段进行混合和匹配。
教程:更高级的东西,转换
杰克逊的一个有用(但不是非常广为人知)的特征是它能够进行任意POJO到POJO的转换。从概念上讲,您可以将转换视为两个步骤的序列:首先,将POJO编写为JSON,然后将JSON绑定到另一种POJO中。实现只是跳过实际生成的JSON,并使用更有效的中间表示。
转换在任何兼容类型之间工作,并且调用非常简单:
ResultType结果=映射器。convertValue(sourceObject,与resultType 。类);
并且只要源和结果类型兼容 - 也就是说,如果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);
// ...并返回
PojoType pojo = mapper.convertValue(propertyMap, PojoType.class);
//解码Base64!(缺省字节[]表示是base64编码字串)
String base64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz";
byte[] binary = mapper.convertValue(base64, byte[].class);
基本上,Jackson可以替代许多Apache Commons组件,用于base64编码/解码和处理“dyna beans”(映射到/来自POJO)等任务。
贡献!
我们希望得到您的贡献,无论是以错误报告,增强请求(RFE),文档或代码补丁的形式。以上所有的主要机制是GitHub Issues系统。
代码贡献的基本规则
实际上只有一个主要规则,即接受任何代码贡献,我们需要从作者那里获得一份填充的贡献者许可协议(CLA)。一个CLA对于任何数量的贡献都足够了,但我们需要一个。或者说,使用我们代码的公司需要它。这让他们的律师对开源使用不那么不满。
核心组件对依赖性的限制
所谓的核心组件(流式api,jackson-annotations和jackson-databind)还存在一个额外的限制:除了以下内容外,不允许任何额外的依赖:
- 核心组件可能依赖于受支持的JDK中包含的任何方法
- 截至Jackson 2.4及以上版本的最低JDK版本为1.6(基线为2.3及更早版本为1.5)
- Jackson-databind(这个包)取决于其他两个(注释,流)。
这意味着任何必须依赖其他API或库的东西都需要构建为扩展,通常是Jackson模块。
与Jackson 1.x的不同之处
项目包含2.0及更高版本:最后(1.x)版本的源代码1.9,可在 Jackson-1 repo上获得。
与1.x“mapper”jar相比的主要差异是:
- Maven构建而不是Ant
- Java包现在
com.fasterxml.jackson.databind
(而不是org.codehaus.jackson.map
)
以上是关于Jackson数据处理及绑定的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot,AWS应用程序上的Jackson数据绑定依赖错误