首页 > 解决方案 > Spring Controller - 测试以使用邮递员在内部接收带有 multipartfile 的嵌套 dto

问题描述

我正在开发一个接受 POST 方法中的 DTO 并基于该 DTO 创建实体的服务。嵌套在里面的是一个多部分文件,它将是将要创建的实体使用的图像。

使用邮递员测试我的后端,我不断收到一个看似空的 DTO。控制器内部的三个日志分别返回null,0null

这就是我设置数据的方式,我很确定这是问题所在:

邮递员形象

我将图像转换为 base64 字符串,据我所知,这是发布嵌套图像的唯一方法。

代码

控制器

@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<InventoryComponentDto> create(@ModelAttributee InventoryComponentDto request) {

    System.out.println(request.getDescription());
    System.out.println(request.getMinimal_supply());
    System.out.println(request.getComponent());

    InventoryComponentDto result = inventoryComponentService.create(request);
    if (result == null) {
        return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
    }

    return ResponseEntity.ok(result);
}

InventoryComponentDto

public class InventoryComponentDto {

    private ComponentDto component;

    private String description;

    private Date createdAt;

    private Date updatedAt;

    private int minimal_supply;

    private int supply;

}

组件Dto

public class ComponentDto {

    private Long id;

    private int number;

    private String name;

    private FileDto image;

}

文件Dto

public class FileDto {

    private String name;

    private String type;

    private String url;

    private MultipartFile data;

}

我在邮递员中充分创建我的 dto 的方法是什么,包括图像?

更新

"status": 400,
"error": "Bad Request",
"message": "JSON parse error: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.package.MCI.dto.InventoryComponentDto[\"component\"]->com.package.MCI.dto.ComponentDto[\"image\"])",
"trace": "org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: (was java.lang.NullPointerException); nested...

标签: springnestedpostmanmultipartform-datadto

解决方案


您需要创建一个自定义杰克逊反序列化器。

//CustomDeserializer

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;

import org.springframework.util.Base64Utils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class CustomDeserializer extends StdDeserializer<FileDTO> {

    public CustomDeserializer() {
        super(FileDTO.class);
    }

    protected CustomDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public FileDTO deserialize(JsonParser jsonParser,
            DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {

        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        String name = node.get("name").asText();
        String url = node.get("url").asText();
        String type = "." + node.get("type").asText();
        String fileBase64 = node.get("data").asText();

        byte[] fileBytes = Base64Utils.decodeFromString(fileBase64);

        FileItem fileItem = new DiskFileItem(name, "image/jpg", false, name + type,
                fileBytes.length, null);
        fileItem.getOutputStream().write(fileBytes);
        fileItem.getOutputStream().flush();
        MultipartFile file = new CommonsMultipartFile(fileItem);
        fileItem.getOutputStream().close();

        FileDTO fileDTO = new FileDTO();
        fileDTO.setName(name);
        fileDTO.setUrl(url);
        fileDTO.setType(type);
        fileDTO.setData(file);

        return fileDTO;

    }

}

并像这样使用它:

//FileDTO

@JsonDeserialize(using = CustomDeserializer.class)
public class FileDTO {

您需要这两个依赖项:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>

推荐阅读