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;
}
}
不确定是否有更好的方法,或者我是否违背了任何最佳实践,但这对我有用。
我需要在单个请求中使用 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;
}
}
不确定是否有更好的方法,或者我是否违背了任何最佳实践,但这对我有用。