Spring 包含 json 内容和附件的 boot swagger multipart

Spring boot swagger multipart with json content and attachment

我需要在单个请求中使用 Swagger-3 上传任何文件内容以及一些元数据信息作为 JSON。因此,我在我的招摇中配置了以下内容:

"requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                    "metadata": {
                        "$ref": "#/components/schemas/Attachment"
                    },
                    "file": {
                        "type": "string", 
                        "format":"binary",
                        "description": "Actual File Attachment"
                    }
                }
              }
            }
          },
          "description": "The Attachment record / entry be created",
          "required": true
 }

当我构建控制器对象时,它转换为以下内容:

@ApiOperation(value = "Upload attachments to a existing Ticket", nickname = "uploadAttachment", notes = "", response = Attachment.class, responseContainer = "List", tags={ "changeRequest", })
@RequestMapping(value = "/changeRequest/attachment/{id}",
        produces = { "application/json" }, 
        consumes = { "multipart/form-data" },
        method = RequestMethod.POST)
public ResponseEntity<List<Attachment>> uploadAttachment(@ApiParam(value = "Identifier of the Change Request",required=true) @PathVariable("id") String id,@ApiParam(value = "Application ID invoking the call" ,required=true) @RequestHeader(value="X-App-Id", required=true) String xAppId,@NotNull @ApiParam(value = "To track unique transaction across multiple systems for audit trail", required = true) @Valid @RequestParam(value = "X-Transaction-Id", required = true) String xTransactionId,@ApiParam(value = "Authorization header" ) @RequestHeader(value="authorization", required=false) String authorization,@ApiParam(value = "", defaultValue="null") @RequestParam(value="metadata", required=false)  Attachment metadata, @ApiParam(value = "file detail") @Valid @RequestPart("file") MultipartFile file) {
    
    ResponseEntity<List<Attachment>> responseEntity = new ResponseEntity<>(HttpStatus.OK);
    responseEntity.getBody().add(metadata);
    return responseEntity;

}

以下是附件架构定义:

"Attachment": {
            "type": "object", 
            "description": "Attachment Metadata definition", 
            "properties": {
                "description": {
                    "type": "string", 
                    "description": "A narrative text describing the content of the attachment"
                }, 
                "href": {
                    "type": "string", 
                    "description": "Reference of the attachment"
                }, 
                "id": {
                    "type": "string", 
                    "description": "Unique identifier of the attachment"
                }, 
                "mimeType": {
                    "type": "string", 
                    "description": "The mime type of the document as defined in RFC 2045 and RFC 2046 specifications."
                }, 
                "name": {
                    "type": "string", 
                    "description": "The name of the file"
                }, 
                "path": {
                    "type": "string", 
                    "description": "The path of the attached file"
                }, 
                "size": {
                    "type": "integer", 
                    "description": "The size of the file (sizeUnit if present indicates the unit, otherwise kilobytes is the default)."
                }, 
                "sizeUnit": {
                    "type": "integer", 
                    "description": "The unit size for expressing the size of the file (MB,kB...)"
                }, 
                "url": {
                    "type": "string", 
                    "description": "Uniform Resource Locator, is a web page address (a subset of URI)"
                }, 
                "validFor": {
                    "$ref": "#/components/schemas/TimePeriod", 
                    "description": "Period of validity of the attachment"
                }, 
                "@type": {
                    "type": "string", 
                    "description": "The class type of the actual resource (for type extension)."
                }, 
                "@schemaLocation": {
                    "type": "string", 
                    "description": "A link to the schema describing a resource (for type extension)."
                }, 
                "@baseType": {
                    "type": "string", 
                    "description": "The base type for use in polymorphic collections"
                }
            }
}

在上面的示例中,附件元数据是我试图作为 SOAP API 测试的一部分传递的内容。但是我不断收到以下错误:

Mon Oct 12 17:06:28 IST 2020:DEBUG:<< "{"timestamp":"2020-10-12T11:36:28.371Z","status":500,"error":"Internal Server Error","message":"Failed to convert value of type 'java.lang.String' to required type 'com.bell.na.nt.change.swagger.model.Attachment'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.bell.na.nt.change.swagger.model.Attachment': no matching editors or conversion strategy found","path":"/changeManagement/api/v1/changeRequest/attachment/1234"}"

为什么字符串没有被转换并映射到 JSON 对象。不确定我遗漏了什么。以下是我的 json 的样子。

{"@baseType": "string",     "@schemaLocation": "string",     "@type": "string",     "description": "string",     "href": "string",     "id": "string",     "mimeType": "string",     "name": "string",     "path": "string",     "size": 0,     "sizeUnit": 0,     "url": "string",     "validFor": {       "endDateTime": "2020-10-11T19:06:40.586Z",       "startDateTime": "2020-10-11T19:06:40.586Z"}}

Postman Request

原来我必须添加一个转换器来将 JSON 的字符串表示形式转换为所需的 Swagger 生成的模型对象,例如:

@Component
public class StringToAttachmentObjectConverter implements Converter<String, Attachment> {
    
    Logger logger = LoggerFactory.getLogger(StringToAttachmentObjectConverter.class);
    
    @Autowired
    private ObjectMapper objectMapper;
    
    DocumentContext docContext = null;

    @Override
    public Attachment convert(String source) {
        try {
            String sourceString = JsonPath.using(NetsUtilityJSONDatumUtils.jsonPathConfig).parse(source).jsonString();
            return objectMapper.readValue(sourceString, Attachment.class);
        } catch (JsonParseException e) {
            logger.error("Error While converting the String: \n" + source, e);
        } catch (JsonMappingException e) {
            logger.error("Error While converting the String: \n" + source, e);
        } catch (IOException e) {
            logger.error("Error While converting the String: \n" + source, e);
        }
        return null;
    }
}

不确定是否有更好的方法,或者我是否违背了任何最佳实践,但这对我有用。