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

Spring Boot序列化问题:新增ChoicesDTO仅需传入问题ID而非完整QuestionDTO

解决新增时仅传入Question的idQ而非完整DTO的问题

这里提供几种实用的解决思路,按需选择:

方案1:拆分请求与响应DTO(推荐)

你的ChoicesResponseDTO更适合作为响应专用DTO(包含完整的Question详情),而新增操作属于请求场景,完全可以单独创建一个请求专用DTO,只保留必要字段:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CreateChoicesRequestDTO {
    private Long idR;
    private ChoicesResponseType choicesResponseType;
    // 仅保留问题ID,无需嵌套完整的QuestionDTO
    private Long questionId;
}

在新增接口里接收这个请求DTO,业务层再把questionId转换成对应的Question实体/DTO即可。这种方式符合单一职责原则,避免DTO混用导致的参数冗余问题。

方案2:通过Jackson注解控制反序列化

如果不想新增DTO,可以直接通过Jackson注解调整字段的序列化/反序列化规则:

方式A:给QuestionDTO字段设置访问权限

修改QuestionDTO,让只有idQ允许被反序列化(即接收请求时只需要这个字段),其他字段仅用于序列化(返回响应时展示):

@Data
@AllArgsConstructor
@NoArgsConstructor
public class QuestionDTO {
    // 允许写入(反序列化),读取(序列化)不受限
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private Long idQ;
    // 仅允许读取(序列化),反序列化时忽略
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private String contentQ;
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private Integer ordreQ;
}

此时新增请求只需要传入{"questionDTO": {"idQ": 123}}即可,Swagger生成的Schema也会自动更新,不再要求传入其他Question字段。

方式B:自定义构造方法配合@JsonCreator

在ChoicesResponseDTO里添加一个接收questionId的构造方法,让Jackson可以直接解析扁平化的参数:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChoicesResponseDTO extends ResponseDTO {
    private Long idR;
    private ChoicesResponseType choicesResponseType;
    private QuestionDTO questionDTO;

    // 标记为Jackson可用的构造方法
    @JsonCreator
    public ChoicesResponseDTO(
        @JsonProperty("idR") Long idR,
        @JsonProperty("choicesResponseType") ChoicesResponseType choicesResponseType,
        @JsonProperty("questionId") Long questionId
    ) {
        this.idR = idR;
        this.choicesResponseType = choicesResponseType;
        this.questionDTO = new QuestionDTO();
        this.questionDTO.setIdQ(questionId);
    }
}

现在请求可以直接传"questionId": 123,不用嵌套questionDTO对象,Swagger也会同步显示这个字段。

方案3:自定义Jackson反序列化器

如果需要更灵活的参数解析逻辑(比如同时支持嵌套questionDTO.idQ和扁平化questionId两种传参方式),可以写一个自定义反序列化器:

public class ChoicesResponseDeserializer extends StdDeserializer<ChoicesResponseDTO> {
    public ChoicesResponseDeserializer() {
        super(ChoicesResponseDTO.class);
    }

    @Override
    public ChoicesResponseDTO deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        ChoicesResponseDTO dto = new ChoicesResponseDTO();
        
        dto.setIdR(node.get("idR").asLong());
        dto.setChoicesResponseType(ChoicesResponseType.valueOf(node.get("choicesResponseType").asText()));
        
        // 兼容两种传参方式:嵌套的questionDTO.idQ 或 直接的questionId
        Long questionId;
        if (node.has("questionDTO") && node.get("questionDTO").has("idQ")) {
            questionId = node.get("questionDTO").get("idQ").asLong();
        } else {
            questionId = node.get("questionId").asLong();
        }
        
        QuestionDTO questionDTO = new QuestionDTO();
        questionDTO.setIdQ(questionId);
        dto.setQuestionDTO(questionDTO);
        
        return dto;
    }
}

然后在ChoicesResponseDTO上指定使用这个反序列化器:

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonDeserialize(using = ChoicesResponseDeserializer.class)
public class ChoicesResponseDTO extends ResponseDTO {
    private Long idR;
    private ChoicesResponseType choicesResponseType;
    private QuestionDTO questionDTO;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:48:23