Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 650
Kalec Avatar asked Sep 13 '26 00:09

Kalec


1 Answers

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);
}
like image 71
Eugene Avatar answered Sep 15 '26 14:09

Eugene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!