Andrey Beletsky
Andrey Beletsky

Reputation: 107

How to convert enum to POJO using mapstruct?

How can I convert enum to POJO using mapstruct and without custom implementation?

e.g.

enum Type {
  T1, T2;

  private String description;

  private Type(String description) {
      this.description = description;
  }

  public String getDescription() { return this.description; }
}

to POJO like

class TypeDto {
   private Type code;
   private String description;
}

FYI, I use MapStruct 1.1.0.Final.

Upvotes: 5

Views: 12163

Answers (3)

Andrey Beletsky
Andrey Beletsky

Reputation: 107

I use this for now

default TypeDto typeToTypeDto(Type type) {
    return new TypeDto(type.name(), type.getName());
}

due to lack of another solution.

Upvotes: 3

Gunnar
Gunnar

Reputation: 18990

It's not something that MapStruct can automatically handle for you. Just implement the mapping by hand. MapStruct does not aim to handle every mapping case for you, but automate the common 80% and let you deal with the more exotic cases yourself.

Upvotes: 1

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48620

You cannot directly convert from an enum to an object.

You would need to create a TypeMapper and an implementation to handle the conversion.

TypeConversion

public class TypeConversion {
    public static void main(String[] args) {
        TypeDto t1 = TypeMapper.INSTANCE.typeToTypeDto(Type.T1);
        TypeDto t2 = TypeMapper.INSTANCE.typeToTypeDto(Type.T2);

        System.out.println(t1);
        System.out.println(t2);
    }
}

Type

public enum Type {
    T1("T-One"),
    T2("T-Two");

    private final String description;

    private Type(String description) {
        this.description = description;
    }

    public String getDescription() {
        return this.description;
    }
}

TypeDto

public class TypeDto {
    private String description;

    public TypeDto() {
        this("");
    }

    public TypeDto(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return String.format("TypeDto { \"description\": \"%s\" }", description);
    }
}

TypeMapper

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface TypeMapper {
    TypeMapper INSTANCE = Mappers.getMapper(TypeMapper.class);

    @Mapping(source = "description", target = "description")
    TypeDto typeToTypeDto(Type type);
 }

TypeMapperImpl

public class TypeMapperImpl implements TypeMapper {
    @Override
    public TypeDto typeToTypeDto(Type type) {
        if (type == null) {
            return null;
        }

        return new TypeDto(type.getDescription());
    }
}

You can make this mapper reusable by creating a generic mapper.

EnumMapper

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper
public interface EnumMapper<T, U extends Enum<?>> {
    @Mapping(target = "description")
    T enumToObject(U type);
 }

EnumMapperImpl

public abstract class EnumMapperImpl<T, U extends Enum<?>> implements EnumMapper<T, U> {
    @Override
    public T enumToObject(U type) {
        if (type == null) {
            return null;
        }

        return convert(type);
    }

    protected abstract T convert(U type);
}

Then you can use this in your TypeMapper.

TypeMapper

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface TypeMapper extends EnumMapper<TypeDto, Type> {
    TypeMapper INSTANCE = Mappers.getMapper(TypeMapper.class);
}

TypeMapperImpl

public class TypeMapperImpl extends EnumMapperImpl<TypeDto, Type> implements TypeMapper {
    @Override
    protected TypeDto convert(Type type) {
        return new TypeDto(type.getDescription());
    }   
}

Upvotes: 1

Related Questions