网站开发工作经验怎么写,温州网站开发网站的制作,自己网站怎么做外链,业务系统管理软件JSON
Jackson是java提供处理json数据序列化和反序列的工具类#xff0c;在使用Jackson处理json前#xff0c;我们得先掌握json。
JSON数据类型
类型示例说明字符串#xff08;String#xff09;hello双引号包裹#xff0c;支持转义字符#xff08;如 \n在使用Jackson处理json前我们得先掌握json。
JSON数据类型
类型示例说明字符串Stringhello双引号包裹支持转义字符如 \n。数字Number42, 3.14, -1e5整数、浮点数或科学计数法表示。布尔值Booleantrue, false仅两个值表示逻辑真/假。对象Object{ key: value }无序的键值对集合。数组Array[1, 2, 3]有序的值列表。Nullnull表示空值或占位符。
例如
# 类型: MapString,ListT
{B: [{id: 1666364264118235829,sort: 1,originalPrice: 20.00},{id: 1666364264118235829,sort: 2,originalPrice: 10.00},{id: 1666364264118235829,sort: 3,originalPrice: 15.00}]
}# 类型MapString,T
{A: {userWithdrawDayCountLimit: 2,userWithdrawDayAmountLimit: 100.00,userWithdrawTotalAmountLimit: 100.00,userPacketDayCountLimit: 100,platformWithdrawDayAmountLimit: 1000.00},B: {userWithdrawDayCountLimit: 3,userWithdrawDayAmountLimit: 100.00,userWithdrawTotalAmountLimit: 100.00,userPacketDayCountLimit: 100,platformWithdrawDayAmountLimit: 1000.00},D1: {userWithdrawDayCountLimit: 2,userWithdrawDayAmountLimit: 100.00,userWithdrawTotalAmountLimit: 100.00,userPacketDayCountLimit: 100,platformWithdrawDayAmountLimit: 1000.00}
}#类型T
{open: false,reachIndex: false,reachRemain: false,withdrawReachRemain: false,pushAcJoin: false,pushWithdraw: false
}#类型MapString,T
# T 包含 ListMapBigDecimal, Double MapBigDecimal, Double MapBigDecimal, Double Integer
{A: {fixed: [{10.00: 1.00}, {1.88: 1.00}, {1.66: 1.00}, {0.88: 1.00}, {0.66: 1.00}],general: {0.01: 0.40,0.02: 0.25,0.03: 0.20,0.04: 0.10,0.05: 0.05},big: {0.06: 0.10,0.08: 0.30,0.10: 0.40,0.15: 0.20},generalToBig: 9},B: {fixed: [{10.00: 1.00}, {1.88: 1.00}, {1.66: 1.00}, {0.88: 1.00}, {0.66: 1.00}],general: {0.01: 0.40,0.02: 0.25,0.03: 0.20,0.04: 0.10,0.05: 0.05},big: {0.06: 0.10,0.08: 0.30,0.10: 0.40,0.15: 0.20},generalToBig: 9}
}JSON易错点
大整数精度丢失 问题JavaScript等语言使用双精度浮点数64位表示所有数字超过 2^53 的整数无法精确表示。 示例 #JSON.parse 后会变成 9007199254740992精度丢失{ id: 9007199254740993 } 解决方案将大整数以字符串传输特别是开发场景中数据库主键ID采用雪花算法生成ID很长得用字符串
浮点数精度问题 问题浮点数在不同系统间传输时可能因精度差异导致微小误差。 示例
{ price: 0.1 }
二进制浮点数0.1 无法精确表示可能导致累加误差如 0.1 0.2 ≠ 0.3推荐使用BigDecimal类型。
Jackson
切入正题在 Java 中使用 Jackson 库处理 JSON 时数字类型的序列化对象转JSON和反序列化JSON转对象需要特别注意数据类型映射、精度问题和配置选项。
Jackson的使用
//反序列化
String outputJson mapper.writeValueAsString(order);
//序列化
Order order mapper.readValue(json, Order.class);
Jackson注解
注解场景用途JsonProperty映射 JSON 字段名 order_id 到 Java 字段 id。JsonFormat将 id 序列化为字符串createTime 格式化为指定日期格式。JsonCreator定义工厂方法用于反序列化时构造 Order 对象。JsonValue序列化 OrderStatus 枚举时输出中文描述而非枚举名称。JsonDeserialize自定义 discountCode 字段的反序列化逻辑从字符串提取数字。JsonIgnore序列化和反序列化忽略该字段
用一个场景玩转这些注解~ 假设订单对象 Order 包含以下需求 订单号id后端字段为 Long但前端要求传输为字符串避免大整数精度丢失。 下单时间createTime以 yyyy-MM-dd HH:mm:ss 格式传输。 订单状态status枚举类型序列化时输出中文描述反序列化时支持数字和字符串。 自定义折扣码discountCode需要将字符串格式 DISCOUNT-1001 转换为纯数字 1001 存储。 订单创建方式通过工厂方法反序列化 JSON。 完整代码实现
1. 订单状态枚举使用 JsonValue 和 JsonCreator
public enum OrderStatus {UNPAID(0, 未支付),PAID(1, 已支付),CANCELLED(2, 已取消);private final int code;private final String desc;OrderStatus(int code, String desc) {this.code code;this.desc desc;}// 序列化时输出中文描述JsonValuepublic String getDesc() {return desc;}// 反序列化时支持从数字或字符串解析JsonCreatorpublic static OrderStatus from(Object value) {if (value instanceof Integer) {int code (Integer) value;for (OrderStatus status : values()) {if (status.code code) return status;}} else if (value instanceof String) {String desc (String) value;for (OrderStatus status : values()) {if (status.desc.equals(desc)) return status;}}throw new IllegalArgumentException(无效的订单状态值: value);}
} 2. 自定义折扣码反序列化器使用 JsonDeserialize
// 自定义反序列化逻辑将 DISCOUNT-1001 转换为 1001
public class DiscountCodeDeserializer extends JsonDeserializerInteger {Overridepublic Integer deserialize(JsonParser p, DeserializationContext ctx) throws IOException {String text p.getText();return Integer.parseInt(text.replace(DISCOUNT-, ));}
}
3. 订单对象使用 JsonFormat、JsonProperty 和 JsonCreator
public class Order {JsonProperty(order_id) // JSON 字段名为 order_id映射到 id 字段JsonFormat(shape JsonFormat.Shape.STRING) // 序列化为字符串private Long id;JsonFormat(shape JsonFormat.Shape.STRING, pattern yyyy-MM-dd HH:mm:ss)private Date createTime;private OrderStatus status;JsonDeserialize(using DiscountCodeDeserializer.class) // 指定自定义反序列化器private Integer discountCode;// 使用工厂方法反序列化JsonCreatorJsonCreatorpublic static Order create(JsonProperty(order_id) Long id,JsonProperty(createTime) Date createTime,JsonProperty(status) OrderStatus status,JsonProperty(discountCode) Integer discountCode) {Order order new Order();order.id id;order.createTime createTime;order.status status;order.discountCode discountCode;return order;}// Getter/Setter 省略
} 4. 测试序列化与反序列化
public class OrderExample {public static void main(String[] args) throws JsonProcessingException {ObjectMapper mapper new ObjectMapper();mapper.setDateFormat(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss));// 反序列化测试String json { \order_id\: \1234567890123456789\, \createTime\: \2023-10-01 14:30:00\, \status\: 1, // 使用数字反序列化 \discountCode\: \DISCOUNT-1001\ };Order order mapper.readValue(json, Order.class);System.out.println(反序列化结果: order.getStatus().getDesc()); // 输出: 已支付System.out.println(折扣码: order.getDiscountCode()); // 输出: 1001// 序列化测试order.setStatus(OrderStatus.CANCELLED);String outputJson mapper.writeValueAsString(order);System.out.println(序列化结果: outputJson);// 输出: {order_id:1234567890123456789,createTime:2023-10-01 14:30:00,status:已取消,discountCode:1001}}
}
Jackson的常见问题
Jackson 根据目标字段的类型自动推断数字类型若类型不匹配可能抛出异常。例如
public class Example {private int value; // 目标字段类型
}// JSON: {value: 10000000000} 超过 int 范围
// 反序列化时会抛出 JsonMappingException: Numeric value (10000000000) out of range of int Java 的 Long 类型最大值为 9,223,372,036,854,775,807超过此值需用 BigInteger例如
public class BigNumberExample {private BigInteger id; // 使用 BigInteger 接收大整数
}// JSON: {id: 123456789012345678901234567890}
//若目标字段为 Long 但值过大会抛出 MismatchedInputException
double 或 float 类型可能导致精度丢失使用 BigDecimal 替代
public class PrecisionExample {JsonFormat(shape JsonFormat.Shape.STRING) // 以字符串形式传输private BigDecimal price;
}// JSON: {price: 0.1} 字符串形式避免二进制精度问题
异常类型原因解决方案MismatchedInputExceptionJSON 数字无法转换为目标类型如溢出使用更大的数据类型如 Long → BigIntegerInvalidFormatException数字格式错误如非数字字符校验输入数据或自定义反序列化逻辑JsonParseExceptionJSON 语法错误如 1,23 代替 1.23修复 JSON 格式
TypeReference类
使用 TypeReference 解决泛型类型擦除问题
String json [{\name\:\Alice\}, {\name\:\Bob\}];
ListUser users mapper.readValue(json, new TypeReferenceListUser() {});
假设需要将 JSON 数组 [{name:Alice}, {name:Bob}] 反序列化为 ListUser
String json [{\name\:\Alice\}, {\name\:\Bob\}];
ListUser users mapper.readValue(json, List.class); // 问题出现
问题由于泛型擦除List.class 丢失了 User 的类型信息Jackson 无法知道 List 中元素的类型默认会反序列化为 ListLinkedHashMap而非 ListUser。
解决方案
ListUser users mapper.readValue(json, new TypeReferenceListUser() {} // 匿名内部类
);
例子
错误用法未处理泛型擦除
String json [{\name\:\Alice\}];
ListUser users mapper.readValue(json, List.class); // 返回 ListLinkedHashMap
User user users.get(0); // 抛出 ClassCastException: LinkedHashMap 无法转为 User
正确用法使用 TypeReference
String json [{\name\:\Alice\}];
ListUser users mapper.readValue(json, new TypeReferenceListUser() {}); // 正确返回 ListUser
User user users.get(0); // 正常访问