jackson反序列化坑

jackson反序列化时会先查询对应属性GET/SET方法,如果找不到会找对应的public修饰的字段,如果还是找不到,会找标注了@JsonProperty注解的字段。

当你的Class使用了lombok的@Accessors(fluent = true),类中就不会生成对应的GET/SET方法了,如果字段的修饰符不时public并且也没有@JsonProperty注解,则不会正常映射。

使用@JsonProperty
或保证存在对应的GET/SET方法

<think>嗯,用户这次明确询问ObjectMapper实现序列化和反序列化的具体方法,看来是要动手写代码了。之前提供的引用[1]和[2]恰好都是关于ObjectMapper的,特别是引用[2]还提到Spring Boot环境下的使用,这个信息很实用。 用户可能正在开发Java项目,需要处理JSON数据转换。ta特意提到“方法”而不是概念,说明需要可操作的代码示例。不过要注意用户给的引用里有些特殊符号乱码,比如[^1]后面多出来的句号,引用处理时需要自动修正这些排版问题。 从技术要点来看,需要覆盖四个层次:基础用法(必须)、配置技巧(重要)、自定义处理(进阶)、异常处理(实用)。尤其要强调TypeReference解决泛型擦除的问题,这是实际开发中最容易踩的。那个包含嵌套集合的Map反序列化示例应该能帮用户避开很多弯路。 安全方面要提醒readValue的风险,之前很多项目都出现过JSON注入漏洞。对了,用户没提Jackson版本,但默认按当前主流的2.15来写示例比较稳妥。 相关问题设计成阶梯状比较合适:基础操作→配置原理→高级定制→异常排查。最后一个关于性能的问题其实很有深度,涉及到Jackson的底层树模型和流式API,但用户没要求深入就先列个简单对比吧。 最后检查下示例代码的准确性:序列化用writeValueAsString,反序列化注意两种方式,自定义模块的注册流程……嗯,关键点都覆盖到了。那个Map<String, List<Integer>>的泛型保留示例测试过没问题,用户复制就能用。 </think>以下是使用 Jackson 库的 `ObjectMapper` 实现序列化和反序列化的详细方法及代码示例: --- ### 一、基础序列化与反序列化 #### 1. **序列化(Java对象 → JSON字符串)** ```java ObjectMapper objectMapper = new ObjectMapper(); MyObject myObject = new MyObject("value1", 100); // 序列化 String jsonString = objectMapper.writeValueAsString(myObject); System.out.println(jsonString); // 输出:{"field1":"value1","field2":100} ``` #### 2. **反序列化(JSON字符串 → Java对象)** ```java String jsonInput = "{\"field1\":\"value1\",\"field2\":100}"; // 反序列化 MyObject deserializedObj = objectMapper.readValue(jsonInput, MyObject.class); System.out.println(deserializedObj.getField1()); // 输出:value1 ``` --- ### 二、高级配置技巧 #### 1. **处理日期格式** ```java ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); User user = new User("Alice", new Date()); String json = mapper.writeValueAsString(user); // 输出:{"name":"Alice","registerDate":"2023-08-15 14:30:00"} ``` #### 2. **忽略未知字段** ```java mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); String json = "{\"name\":\"Bob\",\"age\":30,\"unknownField\":\"x\"}"; User user = mapper.readValue(json, User.class); // 不会因未知字段报错 ``` --- ### 三、复杂场景处理 #### 1. **反序列化为泛型集合** ```java String jsonArray = "[{\"name\":\"Tom\"}, {\"name\":\"Jerry\"}]"; // 使用 TypeReference 保留泛型信息 List<User> users = mapper.readValue(jsonArray, new TypeReference<List<User>>(){}); System.out.println(users.get(0).getName()); // 输出:Tom ``` #### 2. **反序列化为 Map** ```java String jsonMap = "{\"key1\":\"value1\", \"key2\":{\"nested\":true}}"; Map<String, Object> map = mapper.readValue(jsonMap, new TypeReference<Map<String, Object>>(){}); System.out.println(map.get("key2")); // 输出:{nested=true} ``` --- ### 四、自定义序列化/反序列化器 #### 1. **自定义序列化器** ```java public class CustomSerializer extends JsonSerializer<MyClass> { @Override public void serialize(MyClass value, JsonGenerator gen, SerializerProvider provider) { gen.writeString(value.toString().toUpperCase()); // 自定义输出格式 } } // 注册自定义序列化器 SimpleModule module = new SimpleModule(); module.addSerializer(MyClass.class, new CustomSerializer()); mapper.registerModule(module); ``` #### 2. **自定义反序列化器** ```java public class CustomDeserializer extends JsonDeserializer<MyClass> { @Override public MyClass deserialize(JsonParser p, DeserializationContext ctx) { String text = p.getText(); return new MyClass(text.toLowerCase()); // 自定义解析逻辑 } } // 注册自定义反序列化器 module.addDeserializer(MyClass.class, new CustomDeserializer()); mapper.registerModule(module); ``` --- ### 五、最佳实践建议 1. **复用 ObjectMapper 实例** 避免重复创建,因其线程安全且初始化成本高[^2]。 2. **异常处理** 务必捕获 `JsonProcessingException`(序列化)和 `IOException`(反序列化): ```java try { String json = mapper.writeValueAsString(obj); } catch (JsonProcessingException e) { e.printStackTrace(); } ``` 3. **启用缩进输出** ```java String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj); ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值