簡體   English   中英

ModelMapper map 值來自 Map

[英]ModelMapper map value from Map

我正在嘗試了解以下用例的 ModelMapper:

class A {
    public String name;
    public Map<String, ATranslation> translations;
}

class ATranslation {
    public String desc;
}

class DTO {
    public String name;
    public String desc;
}

假設構造函數、Getter 和 Setter。

public class App {
    public static void main(String[] args) {
       Map<String, ATranslation> translations = new HashMap<>();
       translations.put("en", new ATranslation("en-desc"));
       translations.put("nl", new ATranslation("nl-desc"));
       A entity = new A("John Wick",translations);

       System.out.println(App.toDto(entity,"en"));
       System.out.println(App.toDto(entity,"nl"));
    }
    
    private static DTO toDto(A entity, String lang) {
        ModelMapper modelMapper = new ModelMapper();

        //how to set up ModelMapper?

        return modelMapper.map(entity, DTO.class);
    }
}

沒有任何設置 output 是:

DTO(name=John Wick, desc=null)
DTO(name=John Wick, desc=null)

轉換器不起作用:

modelMapper
    .createTypeMap(A.class, DTO.class)
    .setConverter(new Converter<A, DTO>() {
       public DTO convert(MappingContext<A, DTO> context) {
          A s = context.getSource();
          DTO d = context.getDestination();
          d.setDesc(s.getTranslation().get(lang).getDesc());
          return d;
       }
   });

postConverter 確實有效,但似乎不是最 ModelMapper 的方式......

modelMapper
    .createTypeMap(A.class, DTO.class)
    .setPostConverter(new Converter<A, DTO>() {
       public DTO convert(MappingContext<A, DTO> context) {
          A s = context.getSource();
          DTO d = context.getDestination();
          d.setDesc(s.getTranslation().get(lang).getDesc()); //tedious, if many fields...
          return d;
       }
   });
DTO(name=John Wick, desc=en-desc)
DTO(name=John Wick, desc=nl-desc)

有沒有更好的方法在這里使用 ModelMapper?

沒有測試它。 這只是一個由研究組成的理論答案。


設計注意事項

由於您對 Post-Converter 的繁瑣實現的擔憂,以下解決方案是由小型組件設計的。

我嘗試將您的映射用例分解為更小的問題,並使用映射框架中的組件解決每個問題。

映射器的力學

查看 bean 或對象或模型映射器通常是如何工作的,可能會對手頭的問題有所了解。

映射器將類型或源類 A 的 object 映射到另一個類型或目標類 B 的新 object。

ModelMapper - 要使用的組件

我嘗試重用 Baeldung 教程中的示例:使用 ModelMapper 的指南 我們需要3個步驟:

(a) 推斷String name到等效目標的屬性或類型映射

(b) 表達式映射:將Map translationString desc的自定義屬性映射

(c) 參數化轉換器,通過String language進行翻譯和查找,提取ATranslation或將其轉換為String desc

我們使用的功能是:

  1. (a) 和 (b) 的屬性映射
  2. (c)轉換器

1. 屬性映射

它以簡單的形式推斷屬性的映射。 它通過將源的屬性映射到目標來實現。 默認情況下,大多數映射器 map 的屬性與按類型或名稱等效的屬性:

字段類型和名稱完美匹配

在您的情況下,這適用於屬性String name

// GIVEN
Map<String, ATranslation> translations = Map.of(
  "en", new ATranslation("en-desc"),
  "nl", new ATranslation("nl-desc")
);
A entity = new A("John Wick", translations);

// SETUP (a) property-mapping by type
TypeMap<A, DTO> typeMap = modelMapper.createTypeMap(A.class, DTO.class);

// WHEN mapping the properties
DTO dto = modelMapper.map(entity, DTO.class);
    
// THEN desc expected to be null
assertNull(dto.getDesc());
assertEquals(entity.getName(), dto.getName());

2. 轉換

在某些用例中,您需要某種類型的轉換,當無法通過簡單等價推斷出 map 的屬性類型或名稱時。

定義一個翻譯工廠方法來配置轉換器。 它會創建一個新的轉換器,或者可以根據需要說“指定語言的解釋器”。

// Converter: translates for specified language, means lookup in the map using a passed parameter
Converter<Map<String, ATranslation>, String> translateToLanguage(final String language) {
    return c -> c.getOrDefault(language, new ATranslation("")).getDesc();  // language needs to be final inside a lambda
}

此方法可用於翻譯或轉換

// SETUP (a) property-mapping as default type-map
TypeMap<A, DTO> typeMap = modelMapper.createTypeMap(A.class, DTO.class);

// (b) map the property translations (even so other type) to desc
typeMap.addMapping(Source::getTranslation, Destination::setDesc);
// (c) add the converter to the property-mapper
typeMap.addMappings(
  mapper -> mapper.using(translateToLanguage("nl")).map(A::getTranslation, DTO::setDesc)
);

// WHEN mapping the properties
DTO dto = modelMapper.map(entity, DTO.class);

// THEN desc expected to be mapped to the specified language's translation
assertEquals(entity.getTranslation().get("nl").getDesc(), dto.getDesc());
assertEquals(entity.getName(), dto.getName());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM