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

如何用@JsonValue移除JSON的items属性名且保留对象其他属性

如何在Jackson中生成包含无键数组的JSON结构?

我需要生成包含数组、Status和id三个属性的JSON,但不想显示数组对应的items属性名。尝试过以下方法但都有问题:

  • 使用@JsonValue注解时,生成的JSON会丢失status和id属性;
  • 试过@JsonUnwrapped注解,无效;
  • 自定义了ResponseSerializer序列化器,但存在多列表时服务会抛出异常。

期望的JSON格式

{
  [
    {
      "property1": "property",
      "property2": "property"
    }
  ],
  "Status": {
    "code": "code",
    "messages": [
      {
        "message1": "message",
        "message2": "message"
      }
    ]
  },
  "id": "123"
}

不期望的JSON格式

{
  "items": [
    {
      "property1": "property",
      "property2": "property"
    }
  ],
  "Status": {
    "code": "code",
    "messages": [
      {
        "message1": "message",
        "message2": "message"
      }
    ]
  },
  "id": "123"
}

现有代码

RetrieveResponse类

public class RetrieveResponse {
    //@JsonUnwrapped even i try this.
    @JsonValue
    private List<Response> items;
    private Status status;
    private String id;

    // 省略getter/setter
}

Status类

public class Status {
    private String code;
    private List<Message> messages;

    // 省略getter/setter
}

自定义序列化器(原)

public class ResponseSerializer extends JsonSerializer<List<Response>> {
    public static final TypeFactory TYPE_FACTORY = TypeFactory.defaultInstance();
    public static final JavaType LIST_TYPE = TYPE_FACTORY.constructCollectionType(List.class, Response.class);

    @Override
    public void serialize(List<Response> responses, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartArray();
        for (Response item : responses) {
            jsonGenerator.writeObject(item);
        }
        jsonGenerator.writeEndArray();
    }

    @Override
    public Class<List<Response>> handledType() {
        return (Class<List<Response>>) LIST_TYPE.getRawClass();
    }
}

解决方案:为RetrieveResponse编写自定义序列化器

问题出在之前的序列化器只针对List,无法同时处理整个对象的其他属性。我们需要为RetrieveResponse类编写专属的序列化器,手动控制整个JSON的生成逻辑:

1. 实现RetrieveResponseSerializer

public class RetrieveResponseSerializer extends JsonSerializer<RetrieveResponse> {
    @Override
    public void serialize(RetrieveResponse response, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        // 直接写入数组,不指定键名
        gen.writeRawValue(serializers.findValueSerializer(List.class).serialize(response.getItems(), gen));
        // 写入Status属性
        gen.writeObjectField("Status", response.getStatus());
        // 写入id属性
        gen.writeStringField("id", response.getId());
        gen.writeEndObject();
    }
}

2. 在RetrieveResponse类上添加注解

修改RetrieveResponse类,去掉@JsonValue,添加@JsonSerialize指定自定义序列化器:

@JsonSerialize(using = RetrieveResponseSerializer.class)
public class RetrieveResponse {
    private List<Response> items;
    private Status status;
    private String id;

    // 保留getter/setter方法
}

为什么之前的方法无效?

  • @JsonValue:该注解会将整个对象序列化为注解属性的值,因此其他属性(status、id)会被忽略;
  • @JsonUnwrapped:Jackson不支持对集合类型使用该注解,无法实现无键数组的效果;
  • 原自定义序列化器:仅针对List类型,当存在多个集合属性时会出现序列化逻辑冲突,导致异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:05:20