javajacksondeep-copy

Tell Jackson to ignore a property that is a array/collection of a specific type


Background

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?


Solution

  • 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().