大数跨境
0
0

Jackson!JSON处理的瑞士军刀ObjectMapper

Jackson!JSON处理的瑞士军刀ObjectMapper Spring全家桶实战案例
2025-05-30
0
导读:Jackson!JSON处理的瑞士军刀ObjectMapper
Spring Boot 3实战案例锦集PDF电子书已更新至100篇!

🎉🎉《Spring Boot实战案例合集》目前已更新128个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

ObjectMapper 是 Jackson 库的核心组件,用于在 Java 对象与 JSON 数据之间进行高效转换。作为一款功能强大且灵活的序列化/反序列化工具,ObjectMapper 几乎支持所有 Java 类型与 JSON 的互转,包括基本类型、集合、自定义对象等。

它提供丰富的配置选项,可自定义命名策略(如驼峰转下划线)、日期格式、空值处理等,满足多样化需求。通过注解(如 @JsonProperty@JsonIgnore),开发者可精细控制序列化行为,无需修改代码逻辑即可调整输出结构。

ObjectMapper 的模块化设计支持扩展功能,例如 JavaTimeModule 解决了 Java 8 日期时间的处理难题。此外,它还支持流式 API(JsonGenerator/JsonParser),适用于处理大型 JSON 文件或网络流。

无论是 REST API 开发、数据持久化还是配置管理,ObjectMapper 都能以简洁的 API 和强大的性能,成为开发者处理 JSON 的首选工具。

2.实战案例

2.1 基本读写操作

基本上我们会使用 readValue / writeValue 方法进行反序列化和序列化操作,这2个方法都提供了很多的重载方法。

首先,我们定义User实体类:

public record User(Long id, String name, int age, String email) {}
  • 从对象到JSON

ObjectMapper objectMapper = new ObjectMapper();User user = new User(666L, "Spring实战案例源码", 33, "xxxooo@qq.com") ;objectMapper.writeValue(System.out, user) ;

运行结果

{"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com"}

ObjectMapper 类的 writeValueAsString 和 writeValueAsBytes 方法可从 Java 对象生成 JSON,并以字符串或字节数组的形式返回生成的 JSON:

String json = objectMapper.writeValueAsString(user) ;
  • 从JSON到对象

ObjectMapper objectMapper = new ObjectMapper();String jsonStr = """  {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com"}  """ ;User user = objectMapper.readValue(jsonStr, User.class) ;System.err.println(user) ;

运行结果

User[id=666, name=Spring实战案例源码, age=33, email=xxxooo@qq.com]

也可以是网络URL

User user = objectMapper.readValue(  URI.create("http://localhost:8080/user.json").toURL(),   User.class) ;
  • 从JSON到JsonNode

ObjectMapper objectMapper = new ObjectMapper();String json = """    {       "id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com",        "info": {"title": "高级架构师"}    }    """;JsonNode jsonNode = objectMapper.readTree(json);String name = jsonNode.get("name").asText();String title = jsonNode.get("info").get("title").asText() ;System.err.println(name + "@" + title) ;

运行结果

Spring实战案例源码@高级架构师
  • 从JSON数组到List集合

我们可以使用 TypeReference 将 JSON 数组字符串解析为 Java 对象列表。

ObjectMapper objectMapper = new ObjectMapper();String json = """    [      {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com"},      {"id":888,"name": "Pack_xg","age": 22,"email": "pack@163.com"}    ]    """;List<User> users = objectMapper.readValue(json, new TypeReference<List<User>>(){});System.err.println(users) ;

运行结果

[  User[id=666, name=Spring实战案例源码, age=33, email=xxxooo@qq.com],   User[id=888, name=Pack_xg, age=22, email=pack@163.com]]
  • 从JSON字符串到Map

ObjectMapper objectMapper = new ObjectMapper();String json = """    {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com"}    """;Map<String, Object> value = objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){}) ;System.err.println(value) ;

运行结果

{id=666, name=Spring实战案例源码, age=33, email=xxxooo@qq.com}

2.2 高级功能

  • 自定义序列化&反序列化功能

在将 JSON 对象转换为 Java 类时,如果 JSON 字符串包含一些新字段,默认的处理过程会抛出异常,如下json字符串:

String json = """    {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com","address": "wlmq"}    """;

当反序列化该json字符串到User对象时将抛出如下的异常:

通过 configure 方法,我们可以扩展默认的处理过程,使其忽略这些新字段:

ObjectMapper objectMapper = new ObjectMapper();String json = """    {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com","address": "wlmq"}    """;objectMapper.configure(  DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

如上配置将不会有任何问题。

另一种选项是基于 FAIL_ON_NULL_FOR_PRIMITIVES,该选项用于定义是否允许基本数据类型(primitives)的值为 null:

objectMapper.configure(  DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVESfalse) ;

类似地,FAIL_ON_NUMBERS_FOR_ENUMS 用于控制枚举(enum)值是否允许以数字形式进行序列化/反序列化:

objectMapper.configure(  DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMSfalse) ;
  • 自定义序列化&反序列化

输入或输出的 JSON 响应的结构与必须进行序列化或反序列化的 Java 类的结构不同,通过自定义序列化解决此类问题:

// 自定义序列化 public class CustomUserSerializer extends StdSerializer<User> {  public CustomUserSerializer() {    this(null);  }  public CustomUserSerializer(Class<User> t) {    super(t);  }  @Override  public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializer) {    jsonGenerator.writeStartObject();    // 序列化User对象时,将只输出id,name两个字段    jsonGenerator.writeNumberField("id", user.id()) ;    jsonGenerator.writeStringField("name", user.name());    jsonGenerator.writeEndObject();  }}

测试代码

ObjectMapper objectMapper = new ObjectMapper();// 注册序列化器SimpleModule module =     new SimpleModule("CustomUserSerializer"new Version(100nullnullnull));module.addSerializer(User.class, new CustomUserSerializer());objectMapper.registerModule(module) ;User user = new User(666L"Spring实战案例源码"33"xxxooo@qq.com") ;System.err.println(objectMapper.writeValueAsString(user)) ;

运行结果

{"id":666,"name":"Spring实战案例源码"}

自定义反序列器

public class CustomUserDeserializer extends StdDeserializer<User> {  public CustomUserDeserializer() {    this(null);  }  public CustomUserDeserializer(Class<?> vc) {    super(vc);  }  @Override  public User deserialize(JsonParser parser, DeserializationContext deserializer) {    ObjectCodec codec = parser.getCodec();    JsonNode node = codec.readTree(parser);    return new User(node.get("id").asLong(), node.get("name").asText(), nullnull);  }}

测试代码

ObjectMapper objectMapper = new ObjectMapper();SimpleModule module =   new SimpleModule("CustomUserDeserializer", new Version(100nullnullnull));module.addDeserializer(User.class, new CustomUserDeserializer());objectMapper.registerModule(module);String jsonStr = """    {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com"}    """ ;User user = objectMapper.readValue(jsonStr, User.class) ;System.err.println(user) ;

运行结果

User[id=666, name=Spring实战案例源码, age=null, email=null]
  • 集合处理

通过 DeserializationFeature 类提供的另一个小巧但实用的功能是,能够从 JSON 数组响应中生成我们想要的集合类型。

数组类型

ObjectMapper objectMapper = new ObjectMapper();String json = """    [      {"id":666,"name":"Spring实战案例源码","age":33,"email":"xxxooo@qq.com"},      {"id":888,"name": "Pack_xg","age": 22,"email": "pack@163.com"}    ]    """;objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);User[] users = objectMapper.readValue(json, User[].class);System.err.println(Arrays.toString(users)) ;

运行结果

[User[id=666, name=Spring实战案例源码, age=33, email=xxxooo@qq.com], User[id=888, name=Pack_xg, age=22, email=pack@163.com]]

List集合

List<User> list = objectMapper.readValue(  jsonCarArray, new TypeReference<List<User>>(){});
3. 性能优化

jackson-module-afterburner是Jackson库的一个高性能优化模块,通过字节码生成技术预编译序列化与反序列化逻辑,显著减少运行时开销。该模块适用于需要处理大规模JSON数据的场景,可无缝集成至Jackson的ObjectMapper中,在不修改原有代码的情况下提升数据转换效率,尤其适合高吞吐量的Web服务或企业级应用。

引入依赖

<dependency>  <groupId>com.fasterxml.jackson.module</groupId>  <artifactId>jackson-module-afterburner</artifactId></dependency>

配置

@Configurationpublic class JacksonConfig {  @Bean  AfterburnerModule afterburnerModule() {    return new AfterburnerModule() ;  }}

通过JMH性能测试

@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)@State(Scope.Thread)@Warmup(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)@Fork(1)public class ObjectMapperWithAndWithoutTest {  private static final ObjectMapper withObjectMapper = new ObjectMapper()      .registerModule(new AfterburnerModule()) ;  private static final ObjectMapper withoutObjectMapper = new ObjectMapper();  private static final User testUser = new User(666L"Spring实战案例源码"33"xxxooo@qq.com") ;  @Benchmark  public String withOutSerialize() throws Exception {    return withoutObjectMapper.writeValueAsString(testUser);  }  @Benchmark  public String withSerialize() throws Exception {      return withObjectMapper.writeValueAsString(testUser);  }  public static void main(String[] args) throws RunnerException {    Options opt = new OptionsBuilder()        .include(ObjectMapperWithAndWithoutTest.class.getSimpleName())        .build();    new Runner(opt).run();  }}

测试结果

差距不明显。


以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

SpringBoot冷门但逆天的5个神级注解,老司机都在偷偷用!

Spring Cloud Gateway 网关非常实用的8个开发技巧,你知道吗?太实用了

高级开发!自定义@Value实时刷新最新配置

太赞了!AOP弃用@Aspect,一个注解让你的代码灵活十倍!

技术专家!@Transactional 炸场升级:回滚+重试一体化

惊呆了!Spring Boot接口定义:8种逆天玩法

这6个Spring高级开发技巧掌握了吗?

Jackson在Spring Boot高级应用技巧【Long精度丢失, @JsonValue, 数据脱敏】

强大!基于Spring Boot自定义条件动态注册组件

必学!Spring Boot结合MDC全方位的日志跟踪(支持跨线程)

生产环境Spring Boot切记要关闭这个开关

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读7
粉丝0
内容832