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

如何不使用switch case从JSON列表实例化不同类型的record对象

最佳实践方案

你当前场景下完全可以基于record支持实现接口的特性完成优雅实现,不需要修改现有record结构,以下是两种可落地的方案:

方案1:使用JSON库原生多态反序列化(首选)

Java 16+支持密封接口(sealed interface),可以先定义一个公共的密封数据接口,所有record实现该接口,再配合JSON序列化库(以最常用的Jackson为例)的多态反序列化能力,完全不需要手写判断逻辑:

  1. 定义公共密封接口,添加Jackson多态注解:
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "class") // 指定通过class字段判断类型
@JsonSubTypes({
    @JsonSubTypes.Type(value = Object1.class, name = "object1"),
    @JsonSubTypes.Type(value = Object2.class, name = "object2"),
    @JsonSubTypes.Type(value = Object3.class, name = "object3")
})
public sealed interface MyData permits Object1, Object2, Object3 {} // 限定只有指定record可以实现该接口
  1. 让你的所有record实现该接口(符合Java规范,类名调整为大驼峰):
public record Object1(String area, ...) implements MyData {}
public record Object2(String colour, ...) implements MyData {}
public record Object3(String height, ...) implements MyData {}
  1. 直接反序列化整个JSON列表即可,Jackson会自动根据class字段生成对应record实例:
ObjectMapper objectMapper = new ObjectMapper();
List<MyData> dataList = objectMapper.readValue(jsonStr, new TypeReference<List<MyData>>() {});

方案2:自定义简单工厂+注册表(无JSON库绑定)

如果你不想依赖序列化库的特性,也可以自己实现工厂注册表,消除硬编码的switch分支:

import com.fasterxml.jackson.databind.JsonNode;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class MyDataFactory {
    // 注册表:key为JSON中class字段的值,value为对应record的构造逻辑
    private static final Map<String, Function<JsonNode, MyData>> DESERIALIZER_REGISTRY = new HashMap<>();

    static {
        DESERIALIZER_REGISTRY.put("object1", node -> new Object1(node.get("area").asText(), ...));
        DESERIALIZER_REGISTRY.put("object2", node -> new Object2(node.get("colour").asText(), ...));
        DESERIALIZER_REGISTRY.put("object3", node -> new Object3(node.get("height").asText(), ...));
    }

    public static MyData parseFromJson(JsonNode jsonNode) {
        String type = jsonNode.get("class").asText();
        Function<JsonNode, MyData> deserializer = DESERIALIZER_REGISTRY.get(type);
        if (deserializer == null) {
            throw new IllegalArgumentException("不支持的对象类型:" + type);
        }
        return deserializer.apply(jsonNode);
    }
}

遍历JSON数组时,对每个元素直接调用MyDataFactory.parseFromJson(node)即可得到对应实例。

用到的设计模式

核心用到工厂方法模式搭配注册表模式,完全替代硬编码的switch分支,符合开闭原则:后续新增类型时,只需要新增对应的record实现、添加映射关系即可,不需要修改原有解析逻辑。


内容的提问来源于stack exchange,提问作者A.Dumas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 06:54:06