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

使用Jackson JsonParser区分独立Customer与CustomerDocument输入的反序列化实现

实现方案

核心思路

通过自定义Jackson流式处理逻辑,直接操作JsonParser游标逐token判断输入类型,全程不加载全量数据:

  • 优先通过根对象的特征字段(isA、customerList)区分输入场景
  • 识别为批量CustomerDocument场景时,直接定位到customerList数组节点,逐个反序列化数组内的Customer对象,无需加载整个数组到内存
  • 识别为单个Customer场景时,直接反序列化根节点即可,单个对象体积极小,无内存压力

代码实现

无需新增额外实体类,仅需实现一个流式处理工具类即可:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.util.function.Consumer;

public class CustomerProcessor {
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 自动兼容两种输入场景,流式处理Customer对象
     * @param input 支持String、byte[]、InputStream等多种输入类型
     * @param customerHandler 单个Customer的处理回调,处理完即回收内存
     * @throws IOException 解析异常
     */
    public void process(Object input, Consumer<Customer> customerHandler) throws IOException {
        // 输入为InputStream时提前包装为支持标记重置的缓冲流,避免根节点元数据读取失败
        if (input instanceof InputStream inputStream && !(inputStream instanceof BufferedInputStream)) {
            input = new BufferedInputStream(inputStream, 1024 * 1024); // 预留1MB缓存存储外层元数据足够
            ((BufferedInputStream) input).mark(1024 * 1024);
        }

        try (JsonParser parser = objectMapper.createParser(input)) {
            // 定位到根对象起始位置
            if (parser.nextToken() != JsonToken.START_OBJECT) {
                throw new IllegalArgumentException("输入不是合法JSON对象");
            }

            // 读取第一个字段判断输入类型
            if (parser.nextToken() != JsonToken.FIELD_NAME) {
                return; // 空对象直接返回
            }
            String firstField = parser.getCurrentName();

            // 匹配到批量文档标识,走流式批量处理逻辑
            if ("isA".equals(firstField) || "customerList".equals(firstField)) {
                // 先跳过isA字段的取值
                if ("isA".equals(firstField)) {
                    parser.nextToken();
                    parser.skipChildren();
                    // 遍历找到customerList字段
                    while (parser.nextToken() == JsonToken.FIELD_NAME) {
                        if ("customerList".equals(parser.getCurrentName())) break;
                        parser.nextToken();
                        parser.skipChildren();
                    }
                }
                // 定位到customerList数组起始位置
                if (parser.nextToken() != JsonToken.START_ARRAY) {
                    throw new IllegalArgumentException("customerList字段不是合法数组");
                }
                // 流式逐个处理数组元素,不加载全量数据
                while (parser.nextToken() != JsonToken.END_ARRAY) {
                    Customer customer = parser.readValueAs(Customer.class);
                    customerHandler.accept(customer);
                }
                return;
            }

            // 单Customer场景,直接读取整个根对象反序列化
            JsonNode rootNode = parser.readValueAsTree();
            Customer customer = objectMapper.treeToValue(rootNode, Customer.class);
            customerHandler.accept(customer);
        }
    }
}

使用示例

public class Test {
    public static void main(String[] args) throws IOException {
        CustomerProcessor processor = new CustomerProcessor();

        // 1. 处理单个Customer输入
        String singleJson = "{\"id\":1,\"name\":\"张三\",\"phone\":\"13xxxxxxxxx\"}";
        processor.process(singleJson, customer -> {
            // 自定义处理逻辑
            System.out.println("处理单个用户:" + customer.getName());
        });

        // 2. 处理批量CustomerDocument输入
        String batchJson = "{\"isA\":\"CustomerDocument\",\"createTime\":\"2024-01-01\",\"customerList\":[{\"id\":1,\"name\":\"张三\"},{\"id\":2,\"name\":\"李四\"}]}";
        processor.process(batchJson, customer -> {
            // 内存中仅保留当前处理的单个Customer对象,支持百万级以上数据量处理
            System.out.println("批量处理用户:" + customer.getName());
        });
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:09:03