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

使用Jackson将特定结构JSON对象解析为对象数组的问题

解决方案:Jackson解析动态"first:second"格式的JSON键

我之前也碰到过类似的动态键解析需求,给你两个实用的方案,看哪种更适配你的场景:

方案一:先转成Map再手动转换(快速直观)

这种方式不需要额外编写序列化逻辑,先把JSON解析成Map<String, Number>,再遍历处理每个键值对,手动拆分键并创建MyClass实例,非常适合快速验证需求。

代码示例:

首先调整你的MyClass(简化构造逻辑,更贴合手动创建场景):

private static class MyClass {
    String first;
    String second;
    Number value;

    public MyClass(String first, String second, Number value) {
        this.first = first;
        this.second = second;
        this.value = value;
    }

    // 可选:添加toString方便调试
    @Override
    public String toString() {
        return "MyClass{" +
                "first='" + first + '\'' +
                ", second='" + second + '\'' +
                ", value=" + value +
                '}';
    }
}

然后执行解析逻辑:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class JsonParserDemo {
    public static void main(String[] args) throws Exception {
        String json = "{ \"x:y\" : 1, \"x:z\" : 2, \"u:v\" : 3 }";
        ObjectMapper mapper = new ObjectMapper();

        // 第一步:将JSON解析为键值对Map
        Map<String, Number> jsonMap = mapper.readValue(json, Map.class);

        // 第二步:遍历Map,拆分键并转换为MyClass列表
        List<MyClass> myClassList = jsonMap.entrySet().stream()
                .map(entry -> {
                    // 按第一个":"分割,避免键中包含多个":"时出现异常
                    String[] parts = entry.getKey().split(":", 2);
                    return new MyClass(parts[0], parts[1], entry.getValue());
                })
                .collect(Collectors.toList());

        // 输出结果调试
        myClassList.forEach(System.out::println);
    }
}

方案二:自定义JsonDeserializer(优雅集成)

如果需要把JSON直接解析成List<MyClass>(或者包含该列表的自定义容器类),可以编写自定义反序列化器,让Jackson自动完成转换逻辑,更适合集成到现有序列化流程中。

代码示例:

首先创建自定义反序列化器:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MyClassListDeserializer extends JsonDeserializer<List<MyClass>> {
    @Override
    public List<MyClass> deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        JsonNode rootNode = parser.getCodec().readTree(parser);
        List<MyClass> myClassList = new ArrayList<>();

        // 遍历JSON对象的所有字段,逐个转换为MyClass实例
        rootNode.fields().forEachRemaining(entry -> {
            String key = entry.getKey();
            String[] parts = key.split(":", 2);
            Number value = entry.getValue().numberValue();
            myClassList.add(new MyClass(parts[0], parts[1], value));
        });

        return myClassList;
    }
}

然后使用这个反序列化器:

// 方式1:直接解析为List<MyClass>
List<MyClass> myClassList = mapper.readValue(json, 
        mapper.getTypeFactory().constructCollectionType(List.class, MyClass.class));

// 方式2:给自定义容器类添加注解(如果需要封装列表)
// 比如:
// public class MyContainer {
//     @JsonDeserialize(using = MyClassListDeserializer.class)
//     private List<MyClass> items;
//     // getter/setter方法
// }
// 之后直接解析:MyContainer container = mapper.readValue(json, MyContainer.class);

注意事项

  • 如果键中可能包含多个:,一定要用split(":", 2)只分割第一个:,保证second部分保留完整的剩余内容。
  • 如果你必须保留MyClass中的@JsonCreator和@JsonProperty注解,可以在创建实例时调用对应的构造方法,比如把new MyClass(parts[0], parts[1], value)换成new MyClass(entry.getKey(), value),但需要在构造方法内部完成键的拆分逻辑。

内容的提问来源于stack exchange,提问作者Ironcache

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:57:46