使用Jackson ObjectMapper实现多对象模型的反序列化
Java多类反序列化实现方案
完全可以实现你描述的需求:先通过通用模型类Species反序列化整个JSON数组,再将特定节点转换为具体模型类(如Human)。下面结合主流的Jackson JSON库给出具体实现步骤和代码示例。
核心思路
- 先将整个JSON数组反序列化为
List<Species>,筛选出目标节点(如specie为HUMAN的条目) - 将筛选出的对象(或对应的JSON节点)转换为具体的子类(如
Human)
前置准备
1. 确保枚举类定义正确
你的模型类中用到了多个枚举类型,需保证枚举常量名称与JSON中的字符串完全一致(大小写敏感):
// Specie枚举 package com.hw.db.sw.species; public enum Specie { HUMAN, BOTHAN, CEREAN, DUROS, EWOK, GAMORREAN, GUNGAN } // Sourcebook枚举 package com.hw.db.sw; public enum Sourcebook { REVISED_CORE_RULEBOOK } // Size枚举 package com.hw.db.sw.species; public enum Size { MEDIUM, SMALL } // Language枚举 package com.hw.db.sw.species; public enum Language { BASIC, BOTHESE, CEREAN, DURESE, EWOKESE, GAMORREAN, GUNGAN }
2. 修正实体类构造函数
Jackson默认需要类提供无参构造函数,因此给Human类添加无参构造:
package com.hw.db.sw.species; import com.hw.db.sw.Sourcebook; import com.hw.db.sw.Species; import java.io.File; import java.util.List; public class Human extends Species { private File biography; private List<Integer> abilities; private Size size; private int speed; private List<Language> fluentLanguages; private List<Language> literateLanguages; // 添加无参构造函数 public Human() { super(); } public Human(Specie specie, Sourcebook sourcebook, File biography, List<Integer> abilities, Size size, int speed, List<Language> fluentLanguages, List<Language> literateLanguages) { super(specie, sourcebook); this.biography = biography; this.abilities = abilities; this.size = size; this.speed = speed; this.fluentLanguages = fluentLanguages; this.literateLanguages = literateLanguages; } // 原有getter/setter方法不变 public File getBiography() { return biography; } public void setBiography(File biography) { this.biography = biography; } public List<Integer> getAbilities() { return abilities; } public void setAbilities(List<Integer> abilities) { this.abilities = abilities; } public Size getSize() { return size; } public void setSize(Size size) { this.size = size; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public List<Language> getFluentLanguages() { return fluentLanguages; } public void setFluentLanguages(List<Language> fluentLanguages) { this.fluentLanguages = fluentLanguages; } public List<Language> getLiterateLanguages() { return literateLanguages; } public void setLiterateLanguages(List<Language> literateLanguages) { this.literateLanguages = literateLanguages; } }
3. 引入Jackson依赖
如果使用Maven,在pom.xml中添加:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- 使用最新稳定版 --> </dependency>
实现代码
方式一:先反序列化为通用类,再转换为具体类
import com.fasterxml.jackson.databind.ObjectMapper; import com.hw.db.sw.Species; import com.hw.db.sw.species.Human; import com.hw.db.sw.species.Specie; import java.io.File; import java.util.List; public class DeserializationDemo { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); File jsonFile = new File("path/to/your/species.json"); // 替换为你的JSON文件路径 // 1. 反序列化整个JSON数组为List<Species> List<Species> speciesList = objectMapper.readValue( jsonFile, objectMapper.getTypeFactory().constructCollectionType(List.class, Species.class) ); // 2. 筛选目标节点并转换为Human对象 for (Species species : speciesList) { if (Specie.HUMAN.equals(species.getSpecie())) { // 直接将Species对象转换为Human,无需中间JSON字符串 Human human = objectMapper.convertValue(species, Human.class); // 使用Human对象 System.out.println("Human Biography: " + human.getBiography().getPath()); System.out.println("Human Abilities: " + human.getAbilities()); break; } } } }
方式二:直接操作JSON节点(更灵活)
如果不需要先处理通用类,可以直接将JSON反序列化为JsonNode,筛选后再转换为具体类:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.hw.db.sw.species.Human; import java.io.File; public class JsonNodeDeserializationDemo { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); File jsonFile = new File("path/to/your/species.json"); // 1. 反序列化为JSON节点数组 JsonNode speciesArray = objectMapper.readTree(jsonFile); // 2. 遍历找到目标节点并转换为Human for (JsonNode node : speciesArray) { if ("HUMAN".equals(node.get("specie").asText())) { Human human = objectMapper.treeToValue(node, Human.class); System.out.println("Human Speed: " + human.getSpeed()); System.out.println("Fluent Languages: " + human.getFluentLanguages()); break; } } } }
关键注意事项
- 枚举匹配:枚举常量名称必须和JSON中的字符串完全一致,Jackson默认按名称匹配枚举
- 无参构造:实体类必须提供无参构造函数,否则Jackson无法实例化对象(也可通过
@JsonCreator注解指定构造函数) - 字段映射:如果类字段名与JSON键名不一致,需用
@JsonProperty("json_key")注解标注字段
内容的提问来源于stack exchange,提问作者TroyPilewski
相关产品推荐
相关产品推荐

