如何不使用switch case从JSON列表实例化不同类型的record对象
最佳实践方案
你当前场景下完全可以基于record支持实现接口的特性完成优雅实现,不需要修改现有record结构,以下是两种可落地的方案:
方案1:使用JSON库原生多态反序列化(首选)
Java 16+支持密封接口(sealed interface),可以先定义一个公共的密封数据接口,所有record实现该接口,再配合JSON序列化库(以最常用的Jackson为例)的多态反序列化能力,完全不需要手写判断逻辑:
- 定义公共密封接口,添加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可以实现该接口
- 让你的所有record实现该接口(符合Java规范,类名调整为大驼峰):
public record Object1(String area, ...) implements MyData {} public record Object2(String colour, ...) implements MyData {} public record Object3(String height, ...) implements MyData {}
- 直接反序列化整个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
相关产品推荐
相关产品推荐

