0

Background

  • I want to clone DTOs that store values from a request in Spring Boot.
  • I don't have control over these DTOs, so I can't add a transient modifier to ignore these fields.

What I tried

I tried to write a method with Jackson's ObjectMapper. You can use @JsonIgnoreType and ObjectMapper#addMixIn() to ignore non-serializable fields according to their class without changing the definition of DTOs.

private Object makeClone(Object obj) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.addMixIn(MultipartFile.class, JacksonMixInForIgnoreType.class);
    try {
        return mapper.readValue(mapper.writeValueAsString(obj), obj.getClass());
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
}

@JsonIgnoreType
class JacksonMixInForIgnoreType {}

Problem

You can't ignore the field like MultipartFile[] fileArray; with this strategy. When you have an array of MultipartFile in a DTO to upload multiple files, the code above throws an exception like this:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.example.uploadingfiles.DeepCopyDto["fileArray"]->org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile[0]->org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])
        at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.13.1.jar:2.13.1]
        at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300) ~[jackson-databind-2.13.1.jar:2.13.1]
 ...

Question

Is there any way to tell Jackson to ignore a property that is an array/collection of a specific type?

SATO Yusuke
  • 1,600
  • 15
  • 39
  • 2
    Have you tried: `.addMixIn(MultipartFile[].class, JacksonMixInForIgnoreType.class)`? It should work in the same way. Which version of Jackson do you use? – Michał Ziober Nov 19 '22 at 23:25

1 Answers1

0

I am using Jackson Databind 2.13.1. The following code works for MultipartFile[] (based on @Michał Ziober's comment):

private Object makeClone(Object obj) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.addMixIn(MultipartFile.class, JacksonMixInForIgnoreType.class);
    mapper.addMixIn(MultipartFile[].class, JacksonMixInForIgnoreType.class);
    try {
        return mapper.readValue(mapper.writeValueAsString(obj), obj.getClass());
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
}

And I couldn't find the way to ignore List<MultipartFile> with ObjectMapper#addMixIn().

SATO Yusuke
  • 1,600
  • 15
  • 39
  • I never tried but you could try something like `TypeReference> typeRef = new TypeReference{};mapper.addMixIn(typeRef.getClass(),JacksonMixInForIgnoreType.class);` – dariosicily Nov 20 '22 at 15:44
  • `TypeReference> typeRef = new TypeReference>(){}; mapper.addMixIn(typeRef.getClass(), JacksonMixInForIgnoreType.class);` doesn't work for me. `typeRef.getClass().toString()` is `class com.example.uploadingfiles.FileUploadController$1`, not `java.util.List`. `mapper.addMixIn(typeRef.getType().getClass(), JacksonMixInForIgnoreType.class);` is also doesn't work for me. – SATO Yusuke Nov 21 '22 at 15:52