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

Quarkus中@Produces(APPLICATION_JSON)自动添加数组包裹和逗号问题

问题描述

使用Quarkus开发REST API时,通过@Produces(MediaType.APPLICATION_JSON)异步返回客户列表,结果被自动添加了不必要的数组包裹和错误的逗号分隔符;改用MediaType.TEXT_PLAIN时结果符合预期。需要保留APPLICATION_JSON类型,解决该序列化异常问题。

异常返回结果

[
  {
  "isA": "customerDocument",
  "createdOn": "2022-10-10T12:29:43",
  "customerBody": {
    "customerList": [,
      {
        "name": "Batman",
        "age": 45,
        "city": "gotham"
      },
      {
        "name": "superman",
        "age": 50,
        "city": "moon"
      },
    ]
  }
}]

期望返回结果

{
  "isA": "customerDocument",
  "createdOn": "2022-10-10T12:29:43",
  "customerBody": {
    "customerList": [
      {
        "name": "Batman",
        "age": 45,
        "city": "gotham"
      },
      {
        "name": "superman",
        "age": 50,
        "city": "moon"
      }
    ]
  }
}

问题代码

@Path("/testData")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Multi<String> test() throws IOException {
    return Multi.createFrom().items(IOUtils.toString(getClass().getResourceAsStream("/TestJSON.json"), StandardCharsets.UTF_8));
}

解决方案

问题根源

Multi.createFrom().items()方法传入String时,会将其拆分为单个字符的流(因为String实现了CharSequence,被当作字符集合处理)。Quarkus处理Multi类型的JSON响应时,会将整个流序列化为JSON数组,每个元素对应流中的一个字符,最终导致异常的JSON结构。

修复方案

1. 将JSON字符串作为单个元素返回

修改Multi的创建方式,确保流中只有一个完整的JSON字符串元素:

@Path("/testData")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Multi<String> test() throws IOException {
    String jsonContent = IOUtils.toString(getClass().getResourceAsStream("/TestJSON.json"), StandardCharsets.UTF_8);
    // 使用item()方法创建包含单个元素的Multi
    return Multi.createFrom().item(jsonContent);
}

2. 改用Uni替代Multi(非流式场景)

如果仅需异步返回单个JSON对象,Uni更适合(专门用于单个异步结果):

@Path("/testData")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<String> test() throws IOException {
    String jsonContent = IOUtils.toString(getClass().getResourceAsStream("/TestJSON.json"), StandardCharsets.UTF_8);
    return Uni.createFrom().item(jsonContent);
}

3. 返回POJO(推荐最佳实践)

避免直接返回JSON字符串,定义对应Java实体类,让Quarkus自动处理序列化,保证类型安全:

// 定义实体类
public class CustomerDocument {
    private String isA;
    private LocalDateTime createdOn;
    private CustomerBody customerBody;

    // 构造函数、Getter、Setter
}

public class CustomerBody {
    private List<Customer> customerList;

    // 构造函数、Getter、Setter
}

public class Customer {
    private String name;
    private int age;
    private String city;

    // 构造函数、Getter、Setter
}

// 修改API方法
@Path("/testData")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<CustomerDocument> test() throws IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule()); // 处理LocalDateTime序列化
    CustomerDocument document = objectMapper.readValue(
        getClass().getResourceAsStream("/TestJSON.json"),
        CustomerDocument.class
    );
    return Uni.createFrom().item(document);
}

内容的提问来源于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 12:45:49