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

Java序列化中如何让UserNo同时支持字符串与列表类型

问题描述

需要用Java的Rest Assured发送如下JSON请求:

{
  "Document1": [
    {
      "UserName": " ABC",
      "UserNo": "1234"
    },
    {
      "UserName": " DEF",
      "UserNo": [
        "2345",
        "4567"
      ]
    },
    {
      "UserName": " MNO",
      "UserNo": "1234"
    }
  ]
}

已创建对应的实体类Document1:

public class Document1{

    private String UserName;
    private String UserNo
    
    public String getUserName(){
       return UserName;
    }
    
    @JsonProperty("UserName")
    public void setUserName(String userName){
       UserName = userName;
    }
    
    public String getUserNo(){
       return UserNo;
    }
    
    @JsonProperty("UserNo")
    public void setUserNo(String userNo){
       UserNo = userNo;
    }
}

其中UserNo字段既可能是字符串类型,也可能是字符串列表类型。如果把UserNo改为List<String>类型:

private List<String> UserNo;

public List<String> getUserNo(){
   return UserNo;
}

@JsonProperty("UserNo")
public void setUserNo(List<String> userNo){
   UserNo = userNo;
}

则仅能兼容UserName为DEF的情况,ABC的情况会序列化失败。

发送请求的addUser类代码如下:

public class addUser{
    
    CreateUser cu = new CreateUser();
    
    List<Document1> dc1 = new ArrayList();
    
    Document1 d1 = new Document1();
    d1.setUserName("ABC");
    d1.setUserNo("1234");
    dc1.add(d1);
    
    Document1 d2 = new Document1();
    d2.setUserName("DEF");
    d2.setUserNo("2345");
    dc1.add(d2);    
}

请问如何实现UserNo字段在序列化时同时支持字符串和列表类型?

解决方案

要让UserNo同时兼容字符串和列表的序列化/反序列化,推荐用Jackson自定义序列化器的方式,既保证类型安全,又能灵活处理不同格式:

方法1:自定义序列化器与反序列化器

  1. 将Document1中的UserNo统一改为List<String>类型,通过自定义逻辑处理序列化和反序列化的格式转换。
  2. 实现自定义序列化器:
public class UserNoSerializer extends JsonSerializer<List<String>> {
    @Override
    public void serialize(List<String> userNos, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (userNos != null && userNos.size() == 1) {
            // 单个元素时输出为字符串
            gen.writeString(userNos.get(0));
        } else {
            // 多个元素或空时输出为数组
            gen.writeObject(userNos);
        }
    }
}
  1. 实现自定义反序列化器:
public class UserNoDeserializer extends JsonDeserializer<List<String>> {
    @Override
    public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        List<String> userNos = new ArrayList<>();
        if (node.isTextual()) {
            // 字符串类型转为单个元素的列表
            userNos.add(node.asText());
        } else if (node.isArray()) {
            // 数组类型遍历添加到列表
            for (JsonNode item : node) {
                userNos.add(item.asText());
            }
        }
        return userNos;
    }
}
  1. 修改Document1类,给UserNo字段添加注解,并新增便捷方法:
public class Document1{

    private String UserName;
    @JsonSerialize(using = UserNoSerializer.class)
    @JsonDeserialize(using = UserNoDeserializer.class)
    private List<String> UserNo;
    
    public String getUserName(){
       return UserName;
    }
    
    @JsonProperty("UserName")
    public void setUserName(String userName){
       UserName = userName;
    }
    
    public List<String> getUserNo(){
       return UserNo;
    }
    
    @JsonProperty("UserNo")
    public void setUserNo(List<String> userNo){
       UserNo = userNo;
    }
    
    // 新增便捷方法,直接传入单个字符串
    public void setUserNo(String userNo){
        this.UserNo = Collections.singletonList(userNo);
    }
}
  1. 调整addUser类的代码适配新逻辑:
import java.util.Arrays;

public class addUser{
    
    CreateUser cu = new CreateUser();
    
    List<Document1> dc1 = new ArrayList();
    
    Document1 d1 = new Document1();
    d1.setUserName("ABC");
    d1.setUserNo("1234");
    dc1.add(d1);
    
    Document1 d2 = new Document1();
    d2.setUserName("DEF");
    d2.setUserNo(Arrays.asList("2345", "4567"));
    dc1.add(d2);    
    
    Document1 d3 = new Document1();
    d3.setUserName("MNO");
    d3.setUserNo("1234");
    dc1.add(d3);
}

方法2:简易Object类型实现(非类型安全)

如果不想编写自定义序列化器,也可以将UserNo定义为Object类型,Jackson会自动根据实际类型输出对应格式,但这种方式缺乏类型校验:

public class Document1{

    private String UserName;
    private Object UserNo;
    
    public String getUserName(){
       return UserName;
    }
    
    @JsonProperty("UserName")
    public void setUserName(String userName){
       UserName = userName;
    }
    
    public Object getUserNo(){
       return UserNo;
    }
    
    @JsonProperty("UserNo")
    public void setUserNo(Object userNo){
       UserNo = userNo;
    }
    
    // 便捷方法
    public void setUserNo(String userNo){
        this.UserNo = userNo;
    }
    
    public void setUserNo(List<String> userNo){
        this.UserNo = userNo;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:48:26