Jackson之ObjectMapper对象的使用
文章目录
- 1 简介
- 2 Jackson的数据绑定
- 3 Jackson ObjectMapper对象示例
- 4 反序列化
- ObjectMapper从JSON属性匹配到Java属性的过程
- 从JSON字符串读取Java对象
- 从JSON Reader对象读取Java对象
- 从JSON文件读取Java对象
- 从URL获取JSON数据读取Java对象
- 从Java InputStream获取JSON数据读取Java对象
- 从字节数组获取JSON数据读取Java对象
- 从JSON数组字符串读取Java对象数组
- 从JSON数组字符串读取Java List对象
- 从JSON字符串读取Java Map对象
- 特殊情况
- 忽略Java对象没有的JSON属性
- JSON属性值为NULL且对应Java原生类型产生的异常
- 定制反序列化过程
- 5 序列化
- 把对象序列化成JSON
- 自定义序列化过程
- 6 Jackson的日期格式化
- Date到long
- Date到String
- 7 Jackson的树模型
- Jackson树模型示例
- JsonNode类
1 简介
Jackson ObjectMapper
类(com.fasterxml.jackson.databind.ObjectMapper
)是使用Jackson解析JSON最简单的方法。Jackson ObjectMapper
可以从字符串、流或文件解析JSON,并创建Java对象或对象图来表示已解析的JSON。将JSON解析为Java对象也称为从JSON反序列化Java对象
Jackson ObjectMapper
也可以从Java对象创建JSON. 从Java对象生成JSON的过程也被称为序列化Java对象到JSON
Jackson对象映射器(Object Mapper)
可以把JSON解析为用户自定义类对象, 或者解析为JSON内置的树模型的对象(详见下文)
2 Jackson的数据绑定
ObjectMapper
对象定义位于Jackson Databind
项目中, 所以应用中要添加相关项目路径或依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.6</version>
</dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.6</version>
</dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version>
</dependency>
3 Jackson ObjectMapper对象示例
返回目录
一个简单的例子:
public class Car {private String brand = null;private int doors = 0;public String getBrand() { return this.brand; }public void setBrand(String brand){ this.brand = brand;}public int getDoors() { return this.doors; }public void setDoors (int doors) { this.doors = doors; }
}
...........................................................
ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
try {Car car = objectMapper.readValue(carJson, Car.class);System.out.println("car brand = " + car.getBrand());System.out.println("car doors = " + car.getDoors());
} catch (IOException e) {e.printStackTrace();
}
如例所见, readValue()
方法的第一个参数是JSON数据源(字符串, 流或者文件), 第二个参数是解析目标Java类, 这里传入的是Car.class
4 反序列化
ObjectMapper从JSON属性匹配到Java属性的过程
返回目录
要想从JSON正确的读取到Java对象, 那么了解Jackson是怎么从JSON对象映射到Java对象就非常重要
默认情况下, Jackson映射一个JSON对象的属性到Java对象, 是用JSON属性的名字在Java对象中查找匹配的getter/setter
方法. Jackson移除了getter/setter
方法名中的get/set
字符部分, 并把方法名剩余字符的第一个字符小写, 得到的就是JSON属性名.
在上一节的例子中, JSON属性的名称是brand
, 匹配了Java类中名为getBrand()/setBrand()
的getter/setter
方法. JSON属性的名称是engineNumber
, 匹配了getEngineNumber()/setEngineNumber()
如果想用其他方法来匹配JSON对象属性和Java对象属性, 可以自定义序列化/反序列化过程, 或者使用其他的Jackson注解
从JSON字符串读取Java对象
返回目录
从JSON字符串读取Java对象非常简单, 前面的例子已经展示了具体过程. JSON字符串作为第一个参数传递给ObjectMapper.readValue()
方法, 参见前例
从JSON Reader对象读取Java对象
返回目录
也可以通过Reader
实例从JSON中读取一个Java对象
ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 4 }";
Reader reader = new StringReader(carJson);
Car car = objectMapper.readValue(reader, Car.class);
从JSON文件读取Java对象
返回目录
也可以通过FileReader
实例从读取JSON(替换上例中的StringReader
即可), 当然, 也可以直接使用File
对象
ObjectMapper objectMapper = new ObjectMapper();
File file = new File("data/car.json");
Car car = objectMapper.readValue(file, Car.class);
从URL获取JSON数据读取Java对象
返回目录
可以通过URL(java.net.URL
)获取JSON数据后读取Java对象
ObjectMapper objectMapper = new ObjectMapper();
URL url = new URL("file:data/car.json");
Car car = objectMapper.readValue(url, Car.class);
这个例子使用了文件URL, 当然也可以使用HTTP URL
从Java InputStream获取JSON数据读取Java对象
返回目录
ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("data/car.json");
Car car = objectMapper.readValue(input, Car.class);
从字节数组获取JSON数据读取Java对象
返回目录
ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
byte[] bytes = carJson.getBytes("UTF-8");
Car car = objectMapper.readValue(bytes, Car.class);
从JSON数组字符串读取Java对象数组
返回目录
ObjectMapper
也可以从JSON数组字符串中读取一组Java对象
String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
Car[] cars2 = objectMapper.readValue(jsonArray, Car[].class);
注意Car
类数组作为readValue()
方法第二个参数的传入方式, 告诉ObjectMapper
期望从JSON读取一组Car
实例
当然了, JSON源不仅是字符串, 也可以是文件, URL, InputStream, Reader等等
从JSON数组字符串读取Java List对象
返回目录
String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> cars1 = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});
注意传递给readValue()
的TypeReference
类型参数. 这个参数告诉Jackson读取一"列"Car对象
- Jackson通过反射来生成Java对象, 但是模板会擦除类型, 所以这里用
TypeReference
进行包装
从JSON字符串读取Java Map对象
返回目录
ObjectMapper
可以从JSON字符串读取一个Java Map
, 当你不知道要提取的JSON的格式的时候非常有用. 一般会把JSON对象读取到一个JavaMap对象
中. 每一个JSON对象的属性都会变成JavaMap
中的键值对.
String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> jsonMap = objectMapper.readValue(jsonObject, new TypeReference<Map<String,Object>>(){});
特殊情况
忽略Java对象没有的JSON属性
返回目录
有时候你要读取的JSON数据的属性要多于你的Java对象的属性, 默认情况下Jackson这时会抛出异常, 含义是无法在Java对象中找到未知属性XXX
但是, 我们有时候又需要允许JSON属性多于要产生的Java对象的属性. 比如, 你想从一个REST服务
获取JSON数据, 但是它包含的内容远多于你所需要的. 这是, 通过配置Jackson的Feature
使能可以让你忽略那些多余的属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
注意 : 也可以用ObjectMapper.enabled()/disabled()
方法进行配置
JSON属性值为NULL且对应Java原生类型产生的异常
返回目录
可以配置ObjectMapper
的Feature
, 使其在JSON字符串包含的属性值是null
, 且该属性对应的Java对象的属性是原生类型(primitive type: int, long, float, double等
)时, 反序列化失败抛出异常.
修改Car类的定义:
public class Car {private String brand = null;private int doors = 0;public String getBrand() { return this.brand; }public void setBrand(String brand){ this.brand = brand;}public int getDoors(){ return this.doors; }public void setDoors (int doors) { this.doors = doors; }
}
注意属性doors
的类型是Java原生类型int
(而不是object
)
现在假设有一个JSON字符串要匹配Car类:
"brand":"Toyota", "doors":null }
注意属性doors
的值是null
Java中的原生数据类型的值不能是null
. 所以ObjectMapper默认会忽略null
值的原生类型的属性, 不过, 你也可以配置ObjectMapper
的Feature
让它抛出异常, 如下:
ObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
通过设置FAIL_ON_NULL_FOR_PRIMITIVES
属性是true
, 你会在试图把null
值的JSON属性解析为Java原生类型属性时抛出异常,如下:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
String carJson = "{ \"brand\":\"Toyota\", \"doors\":null }";
Car car = objectMapper.readValue(carJson, Car.class);
抛出的异常信息如下:
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException:Cannot map `null` into type int(set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)at [Source: (String)"{ "brand":"Toyota", "doors":null }"; line: 1, column: 29] (through reference chain: jackson.Car["doors"])
定制反序列化过程
返回目录
有时候, 我们需要用不同于ObjectMapper
默认的方式来反序列化JSON字符串到一个Java对象. 这时, 可以添加一个自定义序列化器(custom deserializer
)到ObjectMapper
, 让它可以按照你设定的方式进行反序列化.
下面是用ObjectMapper
注册和使用自定义反序列化器的示例:
String json = "{ \"brand\" : \"Ford\", \"doors\" : 6 }";
//定义一个模型,该模型使用`CarDeserializer`作为反序列化器
SimpleModule module = new SimpleModule("CarDeserializer", new Version(3, 1, 8, null, null, null));
//指定反序列化器作用的Java类(Car类)
module.addDeserializer(Car.class, new CarDeserializer(Car.class));ObjectMapper mapper = new ObjectMapper();
//为ObjectMapper添加一个序列化/反序列化的模型
mapper.registerModule(module);
//反序列化Car类
Car car = mapper.readValue(json, Car.class);
下面是这里的反序列化器CarDeserializer
的定义:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;import java.io.IOException;public class CarDeserializer extends StdDeserializer<Car> {public CarDeserializer(Class<?> vc) {super(vc);}@Overridepublic Car deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {Car car = new Car();while(!parser.isClosed()){JsonToken jsonToken = parser.nextToken();if(JsonToken.FIELD_NAME.equals(jsonToken)){String fieldName = parser.getCurrentName();System.out.println(fieldName);jsonToken = parser.nextToken();if("brand".equals(fieldName)){car.setBrand(parser.getValueAsString());} else if ("doors".equals(fieldName)){car.setDoors(parser.getValueAsInt());}}}return car;}
}
5 序列化
把对象序列化成JSON
返回目录
ObjectMapper
实例也可以用来从一个对象生成JSON数据. 可以使用下列方法:
- writeValue()
- writeValueAsString()
- writeValueAsBytes()
下面是一个把Car
对象序列化为JSON的例子:
ObjectMapper objectMapper = new ObjectMapper();Car car = new Car();
car.brand = "BMW";
car.doors = 4;objectMapper.writeValue(new FileOutputStream("data/output-2.json"), car);
这里首先创建了一个ObjectMapper
实例和一个Car
实例, 然后调用ObjectMapper
的writeValue()
方法把Car
实例转换为JSON后输出到FileOutputStream
writeValueAsString()
和writeValueAsBytes()
也可以从对象生成JSON, 并且返回一个String
或Byte数组
的JSON, 如下:
ObjectMapper objectMapper = new ObjectMapper();Car car = new Car();
car.brand = "BMW";
car.doors = 4;String json = objectMapper.writeValueAsString(car);
System.out.println(json);
输出结果是:
{"brand":"BMW","doors":4}
自定义序列化过程
返回目录
有时候你又不想用Jackson默认的序列化过程把一个Java对象变成JSON. 比如, 你可能在JSON中使用和Java对象不同的属性名称, 或者你想完全忽略某些属性
Jackson可以为ObjectMapper
设置一个自定义序列化器(custom serializer)
这个序列化器会注册为序列化某个实际的类, 然后在ObjectMapper
执行序列化时调用, 比如序列化Car对象
下例展示了如何为Car类
注册一个自定义序列化器
:
//用Car类初始化序列化器CarSerializer
CarSerializer carSerializer = new CarSerializer(Car.class);
ObjectMapper objectMapper = new ObjectMapper();
//新建一个序列化模型, 序列化器使用CarSerializer类
SimpleModule module = new SimpleModule("CarSerializer", new Version(2, 1, 3, null, null, null));
//注册carSerializer用于序列化Car
module.addSerializer(Car.class, carSerializer);objectMapper.registerModule(module);Car car = new Car();
car.setBrand("Mercedes");
car.setDoors(5);String carJson = objectMapper.writeValueAsString(car);
输出结果是:
{"producer":"Mercedes","doorCount":5}
下面是CarSerializer
类定义:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;import java.io.IOException;public class CarSerializer extends StdSerializer<Car> {protected CarSerializer(Class<Car> t) {super(t);}@overridepublic void serialize(Car car, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)throws IOException {jsonGenerator.writeStartObject();jsonGenerator.writeStringField("producer", car.getBrand());jsonGenerator.writeNumberField("doorCount", car.getDoors());jsonGenerator.writeEndObject();}
}
注意 : serialize
的第二个参数是一个JsonGenerator
实例, 你可以使用该实例序列化一个对象, 这里是Car
对象
6 Jackson的日期格式化
返回目录
默认情况下, Jackson会把一个java.util.Date
对象序列化为一个long
型值, 也就是从1970-01-1
到现在的毫秒数, 当然, Jackson也支持把日期格式化为字符串.
Date到long
返回目录
首先看看Jackson默认的把Date
序列化为long
的过程, 如下是一个包含Date
类型属性的Java类:
public class Transaction {private String type = null;private Date date = null;public Transaction() {}public Transaction(String type, Date date) {this.type = type;this.date = date;}public String getType() {return type;}public void setType(String type) {this.type = type;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}
}
用ObjectMapper
序列化Transaction
类对象的过程和其他Java对象一样:
Transaction transaction = new Transaction("transfer", new Date());ObjectMapper objectMapper = new ObjectMapper();
String output = objectMapper.writeValueAsString(transaction);System.out.println(output);
序列化结果:
{"type":"transfer","date":1516442298301}
属性date
被序列化为了一个long
型整数
Date到String
返回目录
long
型的序列化可读性很差, 因而Jackson提供了文本格式的日期序列化. 可以为ObjectMapper
指定一个SimpleDateFormat
实例来带格式提取Jackson日期
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
objectMapper2.setDateFormat(dateFormat);String output2 = objectMapper2.writeValueAsString(transaction);
System.out.println(output2);
序列化结果:
{"type":"transfer","date":"2018-01-20"}
可以看到, 属性date
被格式化为一个字符串
7 Jackson的树模型
返回目录
Jackson内置了一个树模型(tree model
)可以用来表示一个JSON对象. 这个树模型非常有用, 比如你不知道收到的JSON数据的结构, 或者你不想新建一个Java类来表示这个JSON数据, 或者你想在使用或者转发JSON数据前对它进行操作.
Jackson的树模型由JsonNode
类实现. 你可以用ObjectMapper
实例把JSON解析为JsonNode
模型, 就像反序列化出一个自定义类对象一样.
下面举例示范JsonNode
的用法.
Jackson树模型示例
返回目录
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
ObjectMapper objectMapper = new ObjectMapper();
try {JsonNode jsonNode = objectMapper.readValue(carJson, JsonNode.class);
} catch (IOException e) {e.printStackTrace();
}
这里, 我们用JsonNode.class
代替了Car.class
对JSON字符串进行解析.
ObjectMapper
提供了更简单的方法得到JsonNode
: readTree()
, 该方法返回的就是一个JsonNode
, 如下:
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
ObjectMapper objectMapper = new ObjectMapper();
try {JsonNode jsonNode = objectMapper.readTree(carJson);
} catch (IOException e) {e.printStackTrace();
}
JsonNode类
返回目录
JsonNode
提供了非常灵活和动态访问的方式, 可以像访问Java对象那样导航浏览JSON
如果把JSON解析为一个JsonNode
实例(或一个JsonNode
实例树), 就可以浏览JsonNode
树模型, 如下例中用JsonNode
访问JSON中的属性,数组,对象等等:
String carJson ="{ \"brand\" : \"Mercedes\", \"doors\" : 5," +" \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +" \"nestedObject\" : { \"field\" : \"value\" } }";
ObjectMapper objectMapper = new ObjectMapper();
try {JsonNode jsonNode = objectMapper.readValue(carJson, JsonNode.class);JsonNode brandNode = jsonNode.get("brand");String brand = brandNode.asText();System.out.println("brand = " + brand);JsonNode doorsNode = jsonNode.get("doors");int doors = doorsNode.asInt();System.out.println("doors = " + doors);JsonNode array = jsonNode.get("owners");JsonNode jsonNode = array.get(0);String john = jsonNode.asText();System.out.println("john = " + john);JsonNode child = jsonNode.get("nestedObject");JsonNode childField = child.get("field");String field = childField.asText();System.out.println("field = " + field);} catch (IOException e) {e.printStackTrace();
}
上面的JSON中包含了一个名为owner
的数组属性和一个名为nestedObject
的对象属性
不管是访问一个属性, 还是数组, 还是内嵌的对象, 都可以用JsonNode
的get()
方法. 为get()
传入一个字符串就可以访问一个JsonNode
实例的一个属性, 传入一个索引就是访问JsonNode
实例代表的数组, 索引代表了你要访问的数组元素位置.
Jackson之ObjectMapper对象的使用相关推荐
- 如何使用Jackson来反序列化对象数组
Jackson数据绑定文档表明Jackson支持反序列化"所有受支持类型的数组",但是我无法确定确切的语法. 对于单个对象,我可以这样做: //json input {" ...
- jackson json转对象 对象转json
一,Jackson使用示例 第1步:创建ObjectMapper对象. 创建ObjectMapper对象.它是一个可重复使用的对象. ObjectMapper mapper = new ObjectM ...
- Jackson 配置 ObjectMapper
配置日期格式 默认情况下,Jackson 会将日期转成 long 值,我们也可以设置日期格式,将日期转成字符串,下面是一个简单的例子. package shangbo.jackson.demo5;im ...
- jackson实现java对象转支付宝/微信模板消息
一.支付宝消息模板大致长这样 {"to_user_id": "","telephone": "xxxxx"," ...
- 使用Jackson忽略JSON对象上的新字段[复制]
本文翻译自:Ignoring new fields on JSON objects using Jackson [duplicate] This question already has an ans ...
- Jackson转换java对象与json对象
本文转载自:http://www.cnblogs.com/songzhen/p/5794494.html 一.导入jar包: (因为之前使用的是jackson 1.x的jar包,所以在把json转换成 ...
- java jackson maven,jackson中objectMapper的使用
Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象 ObjectMapper类是Jackson库的主要类.它称为ObjectMappe ...
- java对象转json jackson_使用Jackson将Java对象转换为JSON
我希望我的JSON看起来像这样: { "information": [{ "timestamp": "xxxx", "featur ...
- SpringCloud工作笔记041---com.fasterxml.jackson.databind.ObjectMapper的使用
JAVA技术交流QQ群:170933152 项目里用到这个: 之前都用阿里,那个fastjson,今天看到了记录 看看我怎么用的: <dependency><groupId>c ...
最新文章
- VS2010中添加第三方库目录VC++ Directories
- 计算机主机磁盘怎么开,电脑bios怎么设置硬盘启动
- Django REST framework 源码解析
- MATLAB solve函数计算得到lambertw函数,用vpa转换即可
- kali linux 网络命令,Kali Linux系统连接Wifi无线网络命令:
- SAP License:SAP常用操作
- 前端学习 第二弹: JavaScript中的一些函数与对象(1)
- 【GDB调试学习笔记】调试逻辑错误
- 米家扫地机器人是石头代工的_石头科技的隐忧:智能扫地机器人前有高山 后有追兵...
- 大学生学计算机笔记本配置,上大学该买什么笔记本?推荐给准大学生的几款本...
- Excel基础(08)IF函数
- GB28181学习笔记2 SIP测试工具 Yate安装使用
- [Latex简明教程] 制作并插入图片
- ECharts 使用xAxis.axisLine.lineStyle.color设置x坐标轴轴线颜色
- 企业微信自建应用获取用户信息
- 中国制造显威,动力电池出货量翻倍增长,已居于绝对领先地位
- 计算机英语 译文,计算机英语参考译文
- 02 资源搜索-全面、快速查找全网你想要的任何信息、情报
- 湖北公安机关出台10条措施服务民营经济发展
- 导致VC2013编译的DLL在VBA中调用时,提示找不到文件的一种可能