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

SmallRye Mutiny:如何修改Multi<String>末尾元素并生成带包装的JSON

问题分析与解决方案

原代码存在的核心问题

  1. 未定义变量错误:代码中generatedEvents变量未声明,属于笔误;即便修正为generatedCustomer,也会导致最后一个客户被重复输出(generatedCustomer中包含带逗号的最后一个客户,lastCustomer又输出去掉逗号的版本)。
  2. 手动拼接JSON的风险:直接拼接字符串极易出现格式错误(比如引号转义、逗号位置、缩进混乱),且无法处理Customer对象JSON中的特殊字符,破坏整体结构。
  3. Multi流处理逻辑错误:给所有客户JSON加逗号后再单独修改最后一个的方式,违背了流式处理的设计,且会产生重复数据。

解决方案

根据数据量大小,提供两种可行方案:

方案一:收集所有数据构建完整对象(适合中小数据量)

通过将所有Customer对象收集到列表中,直接构建目标JSON结构的Java对象,再序列化输出,完全避免手动拼接的风险。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.Instant;
import java.util.List;

public class CustomerGeneratorService {
    public static Multi<String> generate(final Input input) {
        final ObjectMapper objectMapper = new ObjectMapper()
                .registerModule(new JavaTimeModule()); // 支持Instant类型序列化

        try {
            // 收集所有生成的Customer对象到List
            return Multi.createFrom().publisher(CustomerGenerator.createModels(input))
                    .collect().asList()
                    .onItem().transform(customers -> {
                        // 构建外层文档对象
                        CustomerDocument document = new CustomerDocument();
                        document.setCreatedOn(Instant.now());
                        document.getCustomerBody().setCustomerList(customers);

                        // 序列化为格式化的JSON字符串
                        try {
                            return objectMapper.writerWithDefaultPrettyPrinter()
                                    .writeValueAsString(document);
                        } catch (JsonProcessingException e) {
                            throw new CustomerException("Failed to serialize customer document", e);
                        }
                    });
        } catch (Exception e) {
            throw new CustomerException("Exception occurred during customer generation", e);
        }
    }

    // 对应目标JSON的DTO类
    static class CustomerDocument {
        private String isA = "customerDocument";
        private Instant createdOn;
        private CustomerBody customerBody = new CustomerBody();

        // Getters & Setters
        public String getIsA() { return isA; }
        public void setIsA(String isA) { this.isA = isA; }
        public Instant getCreatedOn() { return createdOn; }
        public void setCreatedOn(Instant createdOn) { this.createdOn = createdOn; }
        public CustomerBody getCustomerBody() { return customerBody; }
        public void setCustomerBody(CustomerBody customerBody) { this.customerBody = customerBody; }

        static class CustomerBody {
            private List<Object> customerList; // 若有Customer实体类,替换为List<Customer>

            // Getters & Setters
            public List<Object> getCustomerList() { return customerList; }
            public void setCustomerList(List<Object> customerList) { this.customerList = customerList; }
        }
    }
}

方案二:流式输出(适合大数据量,避免内存占用)

通过Multi.index()跟踪元素位置,仅给非第一个客户的JSON添加前置逗号,配合流式拼接首尾结构,实现无内存压力的输出。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.Instant;

public class CustomerGeneratorService {
    public static Multi<String> generate(final Input input) {
        final ObjectMapper objectMapper = new ObjectMapper()
                .registerModule(new JavaTimeModule());

        try {
            // 生成JSON开头部分
            String start = String.format("{\n  \"isA\": \"customerDocument\",\n  \"createdOn\": \"%s\",\n  \"customerBody\": {\n    \"customerList\": [\n",
                    Instant.now().toString());

            // 处理每个Customer,根据索引决定是否添加前置逗号
            Multi<String> customerEntries = Multi.createFrom().publisher(CustomerGenerator.createModels(input))
                    .index() // 获取带索引的元素(Tuple2<Long, Customer>)
                    .onItem().transform(tuple -> {
                        try {
                            String customerJson = objectMapper.writerWithDefaultPrettyPrinter()
                                    .writeValueAsString(tuple.getItem2());
                            // 第一个元素不加前置逗号,后续元素添加
                            return tuple.getItem1() > 0 ? ",\n      " + customerJson : "      " + customerJson;
                        } catch (JsonProcessingException e) {
                            throw new CustomerException("Failed to serialize customer", e);
                        }
                    });

            // 生成JSON结尾部分
            String end = "\n    ]\n  }\n}";

            // 拼接所有流式部分
            return Multi.createBy().concatenating()
                    .streams(Multi.createFrom().items(start), customerEntries, Multi.createFrom().items(end));
        } catch (Exception e) {
            throw new CustomerException("Exception occurred during customer generation", e);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:15:40