ObjectMapper[jackson]常用配置及异常处理

2024-09-04 00:20

本文主要是介绍ObjectMapper[jackson]常用配置及异常处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 Java 开发中,Jackson 是最常用的 JSON 处理库之一。ObjectMapper 是 Jackson 的核心类,用于在 Java 对象与 JSON 数据之间进行转换。通过 configure() 方法,我们可以配置 ObjectMapper 的各种特性,以满足不同的需求。本文将详细讲解 ObjectMapper.configure() 方法可以配置的参数及其作用。

ObjectMapper.configure() 方法介绍

ObjectMapper.configure() 方法允许开发者在序列化和反序列化过程中控制 Jackson 的行为。该方法接收两个参数:

  • 特性枚举:决定配置的具体行为。
  • 布尔值:启用 (true) 或禁用 (false) 特性。

Jackson 提供了多种特性,可以通过不同的枚举来控制。主要包括以下几类:

  1. SerializationFeature
  2. DeserializationFeature
  3. JsonParser.Feature
  4. JsonGenerator.Feature
  5. MapperFeature
  6. StreamReadFeature 和 StreamWriteFeature

SerializationFeature

SerializationFeature 用于控制 Java 对象序列化为 JSON 时的行为。常用特性包括:

  • WRITE_DATES_AS_TIMESTAMPS

    • 默认值true
    • 说明:将日期(如 java.util.Datejava.time 类)序列化为时间戳(长整型)。如果设置为 false,日期将以 ISO-8601 字符串格式输出。
  • INDENT_OUTPUT

    • 默认值false
    • 说明:启用后,输出的 JSON 将使用缩进格式,使其更加美观(即 pretty-print)。
  • FAIL_ON_EMPTY_BEANS

    • 默认值true
    • 说明:序列化空的 Java 对象(没有任何字段或属性)时会引发异常。如果设置为 false,空对象会被序列化为空的 JSON 对象 {}
  • WRAP_ROOT_VALUE

    • 默认值false
    • 说明:启用后,序列化的 JSON 将根值包裹在一个键中,该键的名称由类的 @JsonRootName 注解决定。

DeserializationFeature

DeserializationFeature 用于控制 JSON 反序列化为 Java 对象时的行为。常见的配置有:

  • FAIL_ON_UNKNOWN_PROPERTIES

    • 默认值true
    • 说明:反序列化过程中,如果遇到未知的 JSON 属性将会引发异常。如果设置为 false,这些属性将被忽略。
  • ACCEPT_SINGLE_VALUE_AS_ARRAY

    • 默认值false
    • 说明:允许将 JSON 中的单一值反序列化为 Java 数组或集合,例如将 "value" 反序列化为 ["value"]
  • UNWRAP_ROOT_VALUE

    • 默认值false
    • 说明:启用后,反序列化的 JSON 必须包含一个包裹根的值,并且只反序列化该根值的内容。
  • READ_UNKNOWN_ENUM_VALUES_AS_NULL

    • 默认值false
    • 说明:如果设置为 true,在反序列化枚举类型时,遇到未知的枚举值将被映射为 null

JsonParser.Feature

JsonParser.Feature 控制 JSON 解析器 (JsonParser) 的行为,以下是一些常见的配置:

  • ALLOW_COMMENTS

    • 默认值false
    • 说明:允许并忽略 JSON 中的注释(///* ... */)。
  • ALLOW_SINGLE_QUOTES

    • 默认值false
    • 说明:允许 JSON 字符串使用单引号(')而不是标准的双引号(")。
  • ALLOW_UNQUOTED_FIELD_NAMES

    • 默认值false
    • 说明:允许 JSON 中的字段名没有引号。
  • ALLOW_TRAILING_COMMA

    • 默认值false
    • 说明:允许在 JSON 对象和数组的末尾存在多余的逗号。

JsonGenerator.Feature

JsonGenerator.Feature 控制 JSON 生成器 (JsonGenerator) 的行为,以下是一些常见的配置:

  • WRITE_NUMBERS_AS_STRINGS

    • 默认值false
    • 说明:所有数字将作为字符串输出。
  • ESCAPE_NON_ASCII

    • 默认值false
    • 说明:非 ASCII 字符将以 Unicode 转义序列(例如 \uXXXX)输出。
  • QUOTE_FIELD_NAMES

    • 默认值true
    • 说明:字段名将被加引号,这符合标准 JSON 规范。

MapperFeature

MapperFeature 控制了 ObjectMapper 的整体映射行为,包括以下一些常见配置:

  • AUTO_DETECT_FIELDS

    • 默认值true
    • 说明:自动检测并序列化/反序列化所有可见的字段(即使没有 @JsonProperty 注解)。
  • DEFAULT_VIEW_INCLUSION

    • 默认值true
    • 说明:默认情况下,所有字段都会包含在序列化中,即使它们不属于特定视图。
  • USE_ANNOTATIONS

    • 默认值true
    • 说明:如果设置为 trueObjectMapper 会尊重类和字段上的 Jackson 注解(如 @JsonProperty@JsonIgnore 等)。

StreamReadFeature 和 StreamWriteFeature

StreamReadFeatureStreamWriteFeature 是在 Jackson 2.12 版本中引入的,用于控制流式读取和写入的行为。例如:

  • INCLUDE_SOURCE_IN_LOCATION (StreamReadFeature)

    • 默认值false
    • 说明:如果设置为 trueJsonParser 将在抛出 JsonParseException 时包含源内容的引用(例如导致错误的 JSON 片段),这有助于调试。
  • STRICT_DUPLICATE_DETECTION (StreamWriteFeature)

    • 默认值false
    • 说明:在检测到重复的 JSON 对象字段时,JsonGenerator 将抛出异常。

如何使用 configure() 方法配置特性

下面是一些使用 configure() 方法配置 ObjectMapper 特性的示例:

ObjectMapper mapper = new ObjectMapper();// 启用或禁用特性
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
mapper.configure(MapperFeature.AUTO_DETECT_FIELDS, true);
mapper.configure(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature(), true);

示例:自定义 JSON 序列化和反序列化行为

假设你有一个 User 类,需要对其进行 JSON 序列化和反序列化。要求包括:

  1. 日期字段应该以 ISO-8601 格式输出,而不是时间戳。
  2. 未知的 JSON 属性在反序列化时应该被忽略。
  3. 输出的 JSON 需要格式化,便于阅读(缩进显示)。

首先,定义一个简单的 User 类:

import java.util.Date;public class User {public String name;public int age;public Date registeredDate;// Constructors, getters, and setterspublic User(String name, int age, Date registeredDate) {this.name = name;this.age = age;this.registeredDate = registeredDate;}public User() {}
}

配置 ObjectMapper 特性

接下来,使用 configure() 方法配置 ObjectMapper,以满足上述要求:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import java.text.SimpleDateFormat;public class ObjectMapperExample {public static void main(String[] args) throws Exception {// 创建 ObjectMapper 实例ObjectMapper mapper = new ObjectMapper();// 配置特性mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // 日期以 ISO-8601 格式输出mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知属性mapper.configure(SerializationFeature.INDENT_OUTPUT, true); // 格式化输出// 也可以设置日期格式mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));// 创建一个 User 对象User user = new User("Alice", 30, new Date());// 序列化 User 对象为 JSONString jsonString = mapper.writeValueAsString(user);System.out.println("序列化的 JSON:\n" + jsonString);// 假设从 JSON 字符串反序列化为 User 对象String inputJson = "{\"name\":\"Bob\",\"age\":25,\"registeredDate\":\"2024-09-02\",\"extraField\":\"ignored\"}";User newUser = mapper.readValue(inputJson, User.class);System.out.println("反序列化后的 User 对象:\n" + newUser.name + ", " + newUser.age + ", " + newUser.registeredDate);}
}

结果输出

运行上面的代码,你将得到以下输出:

序列化的 JSON(日期以 ISO-8601 格式,格式化输出):

{"name" : "Alice","age" : 30,"registeredDate" : "2024-09-02"
}

反序列化后的 User 对象(忽略未知属性 extraField):

Bob, 25, Mon Sep 02 00:00:00 UTC 2024

代码解析

  • mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    • 这个配置使得日期字段在序列化时以 ISO-8601 格式输出,而不是默认的时间戳。
  • mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    • 通过这个配置,Jackson 在反序列化时会忽略 JSON 中的未知属性,避免抛出异常。
  • mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
    • 启用 JSON 格式化输出,使其更具可读性,特别是在调试或日志中使用时。
  • mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
    • 这进一步定制了日期的输出格式,使日期字段严格遵循 yyyy-MM-dd 格式。

异常排查

在使用 Jackson 进行 JSON 序列化和反序列化时,可能会遇到各种异常。以下是一些常见的异常及其排查方法:

1. JsonParseException

描述JsonParseException 通常发生在解析 JSON 时,出现了格式错误、意外结束或其他问题。

常见原因

  • JSON 数据不完整,导致解析中途结束。
  • JSON 格式不正确,例如缺少大括号或方括号。
  • 遇到非法字符或不被支持的 JSON 语法。

解决方法

  • 验证 JSON 数据的完整性,确保数据在传输或存储过程中没有被截断。
  • 使用在线 JSON 校验工具检查 JSON 数据的格式。
  • 捕获异常,并在日志中记录错误位置和具体内容,帮助调试。Jackson 2.12 及以上版本提供了 StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION 特性。启用此特性后,抛出的 JsonParseException 中将包含源内容的位置引用(例如引发错误的 JSON 片段),这有助于快速定位问题。
try {ObjectMapper mapper = new ObjectMapper();mapper.configure(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature(), true);MyObject obj = mapper.readValue(jsonString, MyObject.class);
} catch (JsonParseException e) {System.err.println("JSON parsing failed: " + e.getMessage());e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}

2. JsonMappingException

描述JsonMappingException 是在映射 JSON 数据到 Java 对象时发生的异常,通常与字段类型不匹配或缺少必要的映射信息有关。

常见原因

  • JSON 字段的类型与 Java 对象的字段类型不匹配。
  • JSON 数据中缺少某个必须存在的字段。
  • Java 对象中的类或字段没有相应的无参构造函数或访问器(getter/setter)。

解决方法

  • 检查 JSON 数据和 Java 对象之间的映射关系,确保字段名和数据类型一致。
  • 如果某些字段是可选的,可以使用 @JsonIgnoreProperties(ignoreUnknown = true) 注解忽略未知字段。
  • 确保 Java 对象中包含无参构造函数和必要的访问器。
try {ObjectMapper mapper = new ObjectMapper();MyObject obj = mapper.readValue(jsonString, MyObject.class);
} catch (JsonMappingException e) {System.err.println("JSON mapping failed: " + e.getMessage());e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}

3. JsonGenerationException

描述JsonGenerationException 在生成 JSON 数据时出现,通常与不合法的 JSON 内容有关。

常见原因

  • 试图将一个不支持序列化的对象写入 JSON。
  • 出现递归引用,导致生成无限循环的 JSON 结构。

解决方法

  • 检查并确保所有对象都可以被序列化。如果需要忽略某些字段,可以使用 @JsonIgnore 注解。
  • 对于递归引用的情况,可以使用 @JsonIdentityInfo@JsonManagedReference@JsonBackReference 注解来处理。
try {ObjectMapper mapper = new ObjectMapper();String jsonString = mapper.writeValueAsString(myObject);
} catch (JsonGenerationException e) {System.err.println("JSON generation failed: " + e.getMessage());e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}

4. InvalidDefinitionException

描述InvalidDefinitionException 是一种在序列化或反序列化过程中定义不正确导致的异常,通常与类型定义、注解配置等问题相关。

常见原因

  • 使用了不受支持的类型或缺少序列化/反序列化定义。
  • 缺少适当的构造函数或无法访问的字段。

解决方法

  • 确保类的定义正确,所有需要序列化/反序列化的字段都有适当的访问权限。
  • 检查类上是否正确使用了 Jackson 的注解,例如 @JsonCreator@JsonProperty 等。
try {ObjectMapper mapper = new ObjectMapper();MyObject obj = mapper.readValue(jsonString, MyObject.class);
} catch (InvalidDefinitionException e) {System.err.println("Invalid definition: " + e.getMessage());e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}

5. UnrecognizedPropertyException

描述UnrecognizedPropertyException 发生在反序列化过程中,JSON 中包含了 Java 对象中未定义的字段。

常见原因

  • JSON 数据包含不属于 Java 对象的额外字段。
  • JSON 数据结构更新后,Java 类未及时更新以反映这些更改。

解决方法

  • 可以通过设置 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIESfalse 来忽略未知字段。
  • 或者使用 @JsonIgnoreProperties(ignoreUnknown = true) 注解来忽略这些未知属性。
try {ObjectMapper mapper = new ObjectMapper();mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);MyObject obj = mapper.readValue(jsonString, MyObject.class);
} catch (UnrecognizedPropertyException e) {System.err.println("Unrecognized property in JSON: " + e.getPropertyName());e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}

结语

Jackson 的 ObjectMapper 是一个功能强大且灵活的工具,通过正确配置特性,你可以精确控制 JSON 序列化和反序列化的行为。然而,在实际使用过程中,难免会遇到各种异常。了解并掌握这些异常的排查方法,可以帮助你更快地定位问题,并提高开发效率。

这篇关于ObjectMapper[jackson]常用配置及异常处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134461

相关文章

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

Redis如何使用zset处理排行榜和计数问题

《Redis如何使用zset处理排行榜和计数问题》Redis的ZSET数据结构非常适合处理排行榜和计数问题,它可以在高并发的点赞业务中高效地管理点赞的排名,并且由于ZSET的排序特性,可以轻松实现根据... 目录Redis使用zset处理排行榜和计数业务逻辑ZSET 数据结构优化高并发的点赞操作ZSET 结