简体   繁体   中英

Customize mapstruct to ignore protobuff fields

Since I've noticed that MapStruct was updated to interact with Protobuff and its builder, I thought about migrating our services to fully use MapStruct.

However we're still writing manual conversions to protobuff messages because it's rather clumsy to write a full mapping, considering we have the target_unmapped = Error policy:

compileJava {
    options.compilerArgs += [
            '-Amapstruct.unmappedTargetPolicy=ERROR'
    ]
}

This means that even a rather simple mapping, of two classes with the same 6 identical field names (a throug f) looks like this:

@Mapper(componentModel = "spring", uses = {...})
public interface ProtoMapperExample {

    @Mapping(target = "aBytes", ignore = true)
    @Mapping(target = "bBytes", ignore = true)
    @Mapping(target = "cBytes", ignore = true)
    @Mapping(target = "dBytes", ignore = true)
    @Mapping(target = "eBytes", ignore = true)
    @Mapping(target = "fBytes", ignore = true)
    @Mapping(target = "mergeFrom", ignore = true)
    @Mapping(target = "clearField", ignore = true)
    @Mapping(target = "clearOneof", ignore = true)
    @Mapping(target = "unknownFields", ignore = true)
    @Mapping(target = "mergeUnknownFields", ignore = true)
    @Mapping(target = "allFields", ignore = true)
    ProtoMessage toMessage(Source s);

}

Which is honestly unacceptable. But the option of turning off the error is just as unacceptable.

Our solution was to simply not use MapStruct for this conversion, and I totally agree. It's cumbersome to say the least.

However if there were a way of configurating our mapper to ignore at least the latter 6 fields (mergeFrom, clearField, clearOneof, unknownFields, mergeUnknownFields, allFields) which one would assume and hope mapstruct did by default. Even that would be an improvement.

But we'd also need a way to ignore fields that end in "*Bytes".

Is there any way of doing this?

MapStruct does not support such ignoring, but you can use Mapping Composition to simplify your mapper. All fields which need to be ignored can be gathered into one or several annotations.
Create composite annotation for ignoring fields

import org.mapstruct.Mapping;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.CLASS)
@Mapping(target = "aBytes", ignore = true)
@Mapping(target = "bBytes", ignore = true)
@Mapping(target = "cBytes", ignore = true)
@Mapping(target = "dBytes", ignore = true)
@Mapping(target = "eBytes", ignore = true)
@Mapping(target = "fBytes", ignore = true)
@Mapping(target = "mergeFrom", ignore = true)
@Mapping(target = "clearField", ignore = true)
@Mapping(target = "clearOneof", ignore = true)
@Mapping(target = "unknownFields", ignore = true)
@Mapping(target = "mergeUnknownFields", ignore = true)
@Mapping(target = "allFields", ignore = true)
public @interface IgnoreProtobuff {
}

Apply @IgnoreProtobuff to your mappers

@Mapper
public interface ProtoMapperExample {
    @IgnoreProtobuff
    ProtoMessage toMessage(Source s);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM