Skip to content

填充嵌套对象字段是多态类型时候,列表中有不同类型的字段,替换失败 #331

Description

@HaiTao-G

你的依赖版本与运行环境

  • JDK 版本:17。
  • Crane4j 版本:2.9.0。

描述你的问题或需求

目前的需求:是一个需要转换的字段是一个定义的接口实现的多态转换,如果列表都是同一个对象类型可以替换成功,如果有不同的对象类型,替换失败;希望不同类型也可以替换成功;代码主要的metadata字段;

问题复现代码或需求的示例代码

`package com.cyber.contentai.task.domain.vo;

import cn.crane4j.annotation.Assemble;
import cn.crane4j.annotation.Disassemble;
import cn.crane4j.annotation.Mapping;
import cn.crane4j.core.executor.handler.ManyToManyAssembleOperationHandler;
import cn.hutool.core.date.DateUtil;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.cyber.common.core.annotation.AssembleDict;
import com.cyber.common.core.container.ContainerNamespace;
import com.cyber.contentai.task.domain.Task;
import com.cyber.contentai.task.domain.convert.MetadataConvert;
import com.cyber.resource.api.domain.RemoteFile;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**

  • ai网关任务回调数据视图对象 biz_task

  • @author duyu

  • @Date 2025-12-16
    */
    @DaTa
    @ExcelIgnoreUnannotated
    @AutoMapper(target = Task.class, uses = MetadataConvert.class)
    public class TaskVo implements Serializable {

    @serial
    private static final long serialVersionUID = 1L;

    /**

    • 主键
      */
      @ExcelProperty(value = "主键")
      private Long id;

    /**

    • 任务名称
      */
      private String taskName;

    /**

    • 创意描述
      */
      private String description;

    /**

    • 类型 图片:1 视频:2 音频:3
      */
      private Integer type;

    /**

    • 关联任务群组id
      */
      @ExcelProperty(value = "关联任务群组id")
      private Long taskGroupId;

    /**

    • 任务id
      */
      @ExcelProperty(value = "任务id")
      private String taskId;

    /**

    • 任务状态 1---待执行 2---执行中 3---执行成功 4---执行失败
      */
      @ExcelProperty(value = "任务状态 1---待执行 2---执行中 3---执行成功 4---执行失败")
      private Integer taskStatus;

    /**

    • 完成时间
      */
      @ExcelProperty(value = "完成时间")
      private Date completeTime;

    private Date createTime;

    /**

    • 与业务有关的冗余字段,业务上如果需要可以存储在该字段
      */
      private String bizData;

    @TableField(typeHandler = JacksonTypeHandler.class)
    @ExcelProperty(value = "任务元数据")
    @Disassemble
    private MetadataVo metadata;

    /**

    • 任务执行成功附件标识id列表
      */
      @ExcelProperty(value = "任务执行成功附件标识id列表")
      @assemble(container = ContainerNamespace.REMOTE_FILE, handlerType = ManyToManyAssembleOperationHandler.class, keyType = Long.class, props = @mapping(ref = "attachmentFileList"))
      private List successFileIdList;

    private List attachmentFileList;

    /**

    • 执行成功描述
      */
      @ExcelProperty(value = "执行成功描述")
      private String successDescribe;

    /**

    • 执行失败描述
      */
      @ExcelProperty(value = "执行失败描述")
      private String failDescribe;

    /**

    • 任务子类型
      */
      private Long subType;

    /**

    • 是否是任务组, 视频组显示true
      */
      private Boolean isGroup;

    /**

    • 任务组是否还在运行中
      */
      private Boolean running;

    /**

    • 子任务
      */
      @Disassemble(type = TaskVo.class)
      private List children;

    /**

    • 只获取到分钟
    • @return
      */
      public String getCreateTimeMinutes() {
      if (this.createTime == null) {
      return null;
      }
      return DateUtil.format(this.createTime, "yyyy-MM-dd HH:mm");
      }

    /**

    • 任务执行文本结果
      */
      @TableField(typeHandler = JacksonTypeHandler.class)
      private List successText;

    @JsonIgnoreProperties(ignoreUnknown = true)
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
    @JsonSubTypes({
    @JsonSubTypes.Type(value = AudioMetadataVo.class, name = "AUDIO"),
    @JsonSubTypes.Type(value = ImgMetadataVo.class, name = "IMG"),
    @JsonSubTypes.Type(value = VideoMetadataVo.class, name = "VIDEO"),
    @JsonSubTypes.Type(value = CommentMetadataVo.class, name = "COMMENT"),
    })
    public interface MetadataVo {

    }

    @DaTa
    @JsonTypeName("AUDIO")
    public static class AudioMetadataVo implements MetadataVo, Serializable {

     @Serial
     private static final long serialVersionUID = 1L;
    
     /**
      * 音色头像id
      */
     @Assemble(container = ContainerNamespace.REMOTE_FILE, keyType = Long.class, props = @Mapping(ref = "timbreAvatarFile"))
     private Long timbreAvatarFileId;
    
     /**
      * 音色头像附件
      */
     private RemoteFile timbreAvatarFile;
    
     /**
      * 音色名称
      */
     private String timbreName;
    
     /**
      * 音色性别
      */
     @AssembleDict(dictType = "timbre_sex", props = @Mapping(src = "dictLabel", ref = "sexDictLabel"))
     private String sexDictValue;
    
     /**
      * 性别字典标签
      */
     private String sexDictLabel;
    
     /**
      * 音频时长
      */
     private Double duration;
    

    }

    @DaTa
    @JsonTypeName("IMG")
    public static class ImgMetadataVo implements MetadataVo, Serializable {

     @Serial
     private static final long serialVersionUID = 5122702285272440200L;
    
     /**
      * 图片比例
      */
     private String imageRatio;
    
     /**
      * 风格
      */
     @AssembleDict(dictType = "image_style", key = "style", props = @Mapping(src = "dictLabel", ref = "styleLabel"))
     private String style;
    

    }

    @DaTa
    @JsonTypeName("VIDEO")
    public static class VideoMetadataVo implements MetadataVo, Serializable {

     @Serial
     private static final long serialVersionUID = 1L;
    
     /**
      * 方向
      */
     @AssembleDict(dictType = "video_unblocking", key = "direction", props = @Mapping(src = "dictLabel", ref = "directionLabel"))
     private String direction;
    
     /**
      * 方向标签
      */
     private String directionLabel;
    
     /**
      * 视频解封头像id
      */
     @Assemble(container = ContainerNamespace.REMOTE_FILE, keyType = Long.class, props = @Mapping(ref = "portraitIdFile"))
     private Long portraitId;
    
     /**
      * 视频解封头像附件
      */
     private RemoteFile portraitIdFile;
    
     /**
      * 存放视频生成的id顺序
      */
     @Assemble(container = ContainerNamespace.REMOTE_FILE, handlerType = ManyToManyAssembleOperationHandler.class, keyType = Long.class, props = @Mapping(ref = "fileNameFileList"))
     private List<Long> fileNameList;
    
    
     private List<RemoteFile> fileNameFileList;
    
     /**
      * 存储解封视频的合集
      */
     @Assemble(container = ContainerNamespace.REMOTE_FILE, handlerType = ManyToManyAssembleOperationHandler.class, keyType = Long.class, props = @Mapping(ref = "reopeningFileList"))
     private List<Long> reopeningFileIdList;
    
    
     private List<RemoteFile> reopeningFileList;
    
     /**
      * 视频组合方向
      */
     private List<String> directionMerge;
    
     /**
      * 视频生成方向
      */
     private List<String> directionReopening;
    
     /**
      * 视频首帧图片id
      */
     @Assemble(container = ContainerNamespace.REMOTE_FILE, keyType = Long.class, props = @Mapping(ref = "frameFile"))
     private Long frameFileId;
    
     /**
      * 视频首帧文件
      */
     private RemoteFile frameFile;
    
     /**
      * 视频时长
      */
     private Integer videoDuration;
    
     /**
      * 创意特效名称
      */
     private String creativeName;
    

    }

    @DaTa
    @JsonTypeName("COMMENT")
    public static class CommentMetadataVo implements MetadataVo, Serializable {

     @Serial
     private static final long serialVersionUID = 1L;
    
     /**
      * 评论字典标签值
      */
     @AssembleDict(dictType = "comment_position", props = @Mapping(src = "dictLabel", ref = "commentPositionLabel"))
     private String standpoint;
    
     /**
      * 评论字典标签
      */
     private String commentPositionLabel;
    
     /**
      * 评论字典标签值
      */
     @AssembleDict(dictType = "comment_style", props = @Mapping(src = "dictLabel", ref = "commentStyleLabel"))
     private String commentStyle;
    
     /**
      * 评论字典标签
      */
     private String commentStyleLabel;
    
     /**
      * 采集内容
      */
     private String collectContent;
    
     /**
      * 评论平台名称
      */
     private String platform;
    
     /**
      * 补充评论观点
      */
     private String viewpoint;
    
     /**
      * 风格评论生成方式
      */
     private Long generationType;
    
     /**
      * 风格评论充d
      */
     private String commentId;
    

    }

    /**

    • 创建人ID
      */
      @assemble(sort = 0, container = ContainerNamespace.USER_INFO,
      props = {@mapping(src = "nickName", ref = "createByName"),
      @mapping(src = "avatar", ref = "avatar")})
      private Long createBy;

    /**

    • 用户昵称
      */
      private String createByName;

    @assemble(sort = 1, container = ContainerNamespace.REMOTE_FILE,
    keyType = Long.class,
    props = @mapping(src = "url", ref = "avatarFile"))
    private String avatar;

    private String avatarFile;

}
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions