文章目录

  • 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原生类型产生的异常

返回目录
可以配置ObjectMapperFeature, 使其在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值的原生类型的属性, 不过, 你也可以配置ObjectMapperFeature让它抛出异常, 如下:

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实例, 然后调用ObjectMapperwriteValue()方法把Car实例转换为JSON后输出到FileOutputStream
writeValueAsString()writeValueAsBytes()也可以从对象生成JSON, 并且返回一个StringByte数组的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的对象属性
不管是访问一个属性, 还是数组, 还是内嵌的对象, 都可以用JsonNodeget()方法. 为get()传入一个字符串就可以访问一个JsonNode实例的一个属性, 传入一个索引就是访问JsonNode实例代表的数组, 索引代表了你要访问的数组元素位置.

Jackson之ObjectMapper对象的使用相关推荐

  1. 如何使用Jackson来反序列化对象数组

    Jackson数据绑定文档表明Jackson支持反序列化"所有受支持类型的数组",但是我无法确定确切的语法. 对于单个对象,我可以这样做: //json input {" ...

  2. jackson json转对象 对象转json

    一,Jackson使用示例 第1步:创建ObjectMapper对象. 创建ObjectMapper对象.它是一个可重复使用的对象. ObjectMapper mapper = new ObjectM ...

  3. Jackson 配置 ObjectMapper

    配置日期格式 默认情况下,Jackson 会将日期转成 long 值,我们也可以设置日期格式,将日期转成字符串,下面是一个简单的例子. package shangbo.jackson.demo5;im ...

  4. jackson实现java对象转支付宝/微信模板消息

    一.支付宝消息模板大致长这样 {"to_user_id": "","telephone": "xxxxx"," ...

  5. 使用Jackson忽略JSON对象上的新字段[复制]

    本文翻译自:Ignoring new fields on JSON objects using Jackson [duplicate] This question already has an ans ...

  6. Jackson转换java对象与json对象

    本文转载自:http://www.cnblogs.com/songzhen/p/5794494.html 一.导入jar包: (因为之前使用的是jackson 1.x的jar包,所以在把json转换成 ...

  7. java jackson maven,jackson中objectMapper的使用

    Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象 ObjectMapper类是Jackson库的主要类.它称为ObjectMappe ...

  8. java对象转json jackson_使用Jackson将Java对象转换为JSON

    我希望我的JSON看起来像这样: { "information": [{ "timestamp": "xxxx", "featur ...

  9. SpringCloud工作笔记041---com.fasterxml.jackson.databind.ObjectMapper的使用

    JAVA技术交流QQ群:170933152 项目里用到这个: 之前都用阿里,那个fastjson,今天看到了记录 看看我怎么用的: <dependency><groupId>c ...

最新文章

  1. VS2010中添加第三方库目录VC++ Directories
  2. 计算机主机磁盘怎么开,电脑bios怎么设置硬盘启动
  3. Django REST framework 源码解析
  4. MATLAB solve函数计算得到lambertw函数,用vpa转换即可
  5. kali linux 网络命令,Kali Linux系统连接Wifi无线网络命令:
  6. SAP License:SAP常用操作
  7. 前端学习 第二弹: JavaScript中的一些函数与对象(1)
  8. 【GDB调试学习笔记】调试逻辑错误
  9. 米家扫地机器人是石头代工的_石头科技的隐忧:智能扫地机器人前有高山 后有追兵...
  10. 大学生学计算机笔记本配置,上大学该买什么笔记本?推荐给准大学生的几款本...
  11. Excel基础(08)IF函数
  12. GB28181学习笔记2 SIP测试工具 Yate安装使用
  13. [Latex简明教程] 制作并插入图片
  14. ECharts 使用xAxis.axisLine.lineStyle.color设置x坐标轴轴线颜色
  15. 企业微信自建应用获取用户信息
  16. 中国制造显威,动力电池出货量翻倍增长,已居于绝对领先地位
  17. 计算机英语 译文,计算机英语参考译文
  18. 02 资源搜索-全面、快速查找全网你想要的任何信息、情报
  19. 湖北公安机关出台10条措施服务民营经济发展
  20. 导致VC2013编译的DLL在VBA中调用时,提示找不到文件的一种可能

热门文章

  1. 和Vue来一场美丽的邂逅
  2. 2012年9月8日参加中国软件开发者大会学习笔记
  3. 辞职时被老板叫去谈话挽留,怎样避免被套路
  4. 算法四:跳楼梯问题2
  5. 万字长文,62道Java核心面试题,一次性打包送给积极向上的你
  6. Keil C51与MDK的合并
  7. 使用ESP8266信标垃圾邮件发送者来跟踪智能手机用户
  8. 【漫画,Java微服务实践百度网盘
  9. 全球及中国二手车市场销量渠道规模及发展格局建议报告2021-2027年
  10. n元齐次线性方程组Ax =0解