如何借助JSON Schema反序列化泛型实体及HashMap<String, Object>?
嘿,我来帮你搞定这两个JSON Schema反序列化的问题,分两种场景给你详细说明,附代码示例:
一、借助JSON Schema反序列化泛型实体
要实现泛型实体的反序列化,核心是保留泛型类型信息+用JSON Schema验证输入格式,这里我们结合常用的everit-json-schema验证库和Jackson序列化库来实现:
步骤说明
- 定义你的泛型实体类
- 编写对应泛型实例的JSON Schema
- 先验证JSON是否符合Schema约束
- 用Jackson的
TypeReference指定泛型具体类型完成反序列化
代码示例
1. 泛型实体类
public class GenericEntity<T> { private String id; private T data; // 生成getter、setter和构造方法 public String getId() { return id; } public void setId(String id) { this.id = id; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
2. JSON Schema文件(比如generic-entity-schema.json)
假设我们要反序列化为GenericEntity<Date>,Schema约束日期字段为ISO 8601格式:
{ "type": "object", "properties": { "id": {"type": "string"}, "data": {"type": "string", "format": "date-time"} }, "required": ["id", "data"] }
3. 反序列化实现代码
import org.everit.json.schema.Schema; import org.everit.json.schema.loader.SchemaLoader; import org.json.JSONObject; import org.json.JSONTokener; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Date; public class GenericDeserializationDemo { public static void main(String[] args) throws Exception { // 加载JSON Schema JSONObject schemaJson = new JSONObject(new JSONTokener( GenericDeserializationDemo.class.getResourceAsStream("/generic-entity-schema.json") )); Schema schema = SchemaLoader.load(schemaJson); // 待处理的JSON字符串 String jsonInput = "{\"id\":\"user_001\",\"data\":\"2024-05-20T14:30:00Z\"}"; JSONObject jsonObject = new JSONObject(jsonInput); // 第一步:验证JSON是否符合Schema规则 schema.validate(jsonObject); // 第二步:反序列化为泛型实体,用TypeReference保留泛型信息 ObjectMapper objectMapper = new ObjectMapper(); // 自动注册日期解析模块,确保日期字符串转成Date类型 objectMapper.findAndRegisterModules(); GenericEntity<Date> entity = objectMapper.readValue( jsonInput, new TypeReference<GenericEntity<Date>>() {} ); // 验证类型:输出class java.util.Date System.out.println("Data字段类型:" + entity.getData().getClass()); } }
二、使用JSON Schema反序列化HashMap<String, Object>(含日期转Date类型)
默认情况下,Jackson会把JSON里的日期字符串转成String类型,要让它自动转成Date,需要配置ObjectMapper的日期解析规则,同时用JSON Schema确保输入格式合法:
步骤说明
- 编写约束HashMap结构的JSON Schema(指定日期字段的格式)
- 配置ObjectMapper,使其自动识别日期格式并转为
Date - 先验证JSON,再反序列化为HashMap
代码示例
1. JSON Schema文件(比如hashmap-schema.json)
{ "type": "object", "properties": { "productName": {"type": "string"}, "launchTime": {"type": "string", "format": "date-time"}, "stockCount": {"type": "integer"} }, "required": ["productName", "launchTime", "stockCount"] }
2. 反序列化实现代码
import org.everit.json.schema.Schema; import org.everit.json.schema.loader.SchemaLoader; import org.json.JSONObject; import org.json.JSONTokener; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.DeserializationFeature; import java.util.HashMap; import java.util.Date; public class HashMapDeserializationDemo { public static void main(String[] args) throws Exception { // 加载JSON Schema JSONObject schemaJson = new JSONObject(new JSONTokener( HashMapDeserializationDemo.class.getResourceAsStream("/hashmap-schema.json") )); Schema schema = SchemaLoader.load(schemaJson); // 待处理的JSON字符串 String jsonInput = "{\"productName\":\"PhoneX\",\"launchTime\":\"2024-06-01T00:00:00Z\",\"stockCount\":500}"; JSONObject jsonObject = new JSONObject(jsonInput); // 验证JSON格式符合Schema schema.validate(jsonObject); // 配置ObjectMapper:处理日期转Date,忽略未知字段(可选) ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 自动注册日期解析模块,支持ISO 8601格式转Date objectMapper.findAndRegisterModules(); // 反序列化为HashMap<String, Object> HashMap<String, Object> resultMap = objectMapper.readValue( jsonInput, new TypeReference<HashMap<String, Object>>() {} ); // 验证类型 System.out.println("launchTime类型:" + resultMap.get("launchTime").getClass()); // 输出class java.util.Date System.out.println("stockCount类型:" + resultMap.get("stockCount").getClass()); // 输出class java.lang.Integer } }
关键注意点
- 依赖准备:确保项目中引入了
everit-json-schema和Jackson的核心依赖(Maven示例):<dependencies> <dependency> <groupId>org.everit.json</groupId> <artifactId>org.everit.json.schema</artifactId> <version>1.14.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> </dependencies> - 日期格式自定义:如果你的日期不是ISO 8601格式,可以通过
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))指定自定义格式。 - 泛型类型保留:不管是泛型实体还是HashMap,都要用
TypeReference来指定类型,避免Java类型擦除导致的泛型信息丢失。
内容的提问来源于stack exchange,提问作者Jéssica Miller
相关产品推荐
相关产品推荐

