You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jackson ObjectMapper实现多对象模型的反序列化

Java多类反序列化实现方案

完全可以实现你描述的需求:先通过通用模型类Species反序列化整个JSON数组,再将特定节点转换为具体模型类(如Human)。下面结合主流的Jackson JSON库给出具体实现步骤和代码示例。

核心思路

  1. 先将整个JSON数组反序列化为List<Species>,筛选出目标节点(如specie为HUMAN的条目)
  2. 将筛选出的对象(或对应的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:35:04