当前位置: 首页 > 知识库问答 >
问题:

使用Orika Mapper进行映射时,类型为List的字段的内容丢失

隗高旻
2023-03-14

对于类型为List的字段,任何人都遇到了同样的问题

情况是我有这个物体和这个区域

List<Map<String, String>> aField

Affield的内容包括:

[
{
"key1" : "val1",
"key2": "val2"
}
]

当对象映射到另一个对象时,该字段的内容丢失给新映射的对象,当我尝试打印时,列表的大小仍然是1,但map的内容是空的(如下):

[
{}
]

我将非常感谢您的帮助。谢谢

代码如下:

这是要映射的类:

public class SampleClass {
    private List<Map<String, String>> aField = new ArrayList<>();
    private String bField;

    public List<Map<String, String>> getaField() {
        return aField;
    }

    public void setaField(List<Map<String, String>> aField) {
        this.aField = aField;
    }

    public String getbField() {
        return bField;
    }

    public void setbField(String bField) {
        this.bField = bField;
    }
}

然后我有了一个映射器(我也在使用spring框架):

@Component
public class TransactionMapper extends ConfigurableMapper {
}

控制器上的某处(用于测试目的):

@Autowired
    TransactionMapper mapper;

    System.out.println("---------------- SAMPLE CLASS ------------- ");
                    SampleClass s1 = new SampleClass();
                    List<Map<String, String>> aField = Lists.newArrayList();
                    Map<String, String> map = new HashMap<>();
                    map.put("key1", "val1");
                    map.put("key2", "val2");
                    aField.add(map);
                    s1.setaField(aField);
                    s1.setbField("Sample text");

                    System.out.println("****** s1 contents ******");
                    System.out.println("--- s1 aField: " + ", list size: " + s1.getaField().size());
                    s1.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
                    System.out.println("--- s1 bField content: " + s1.getbField());
                    System.out.println("****** end of s1 contents ******");

                    SampleClass s2 = new SampleClass();
                    mapper.map(s1, s2);
                    System.out.println("****** s2 contents ******");
                    System.out.println("--- s2 aField: " + ", list size: " + s2.getaField().size());
                    s2.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
                    System.out.println("--- s2 bField content: " + s2.getbField());
                    System.out.println("****** end of s2 contents ******");

                    System.out.println("---------------- SAMPLE CLASS ------------- ");

输出:

****** s1 contents ******
--- s1 aField: , list size: 1
key1:val1
key2:val2
--- s1 bField content: Sample text
****** end of s1 contents ******
****** s2 contents ******
--- s2 aField: , list size: 1
--- s2 bField content: Sample text
****** end of s2 contents ******
---------------- SAMPLE CLASS ------------- 

如您所见,s2的aField没有打印内容。


共有1个答案

阎劲
2023-03-14

经过一番研究,我发现了以下解决方案:

  • 使用CustomMapper而不是ConfigurableMapper

首先将此添加到TransactionMapper类:

public class TransactionMapper extends ConfigurableMapper{

    public TransactionMapper(MapperFactory f) {
        configure(f);
    } 

    public void configure(MapperFactory f) {
        f.classMap(SampleClass.class, SampleClass.class).customize(new CustomMapper<SampleClass, SampleClass>() {
            //Override mapping method and set source fields to destination fields
            @Override
            public void mapAtoB(SampleClass source, SampleClass destination, MappingContext context) {
                destination.setaField(source.getaField());
                destination.setbField(source.getbField());
            }
        }).byDefault().register();
    }
}

那么你的主课应该是这样的:

...
MapperFactory factory = new DefaultMapperFactory.Builder().build(); //Create the mapper factory
TransactionMapper mapper = new TransactionMapper(factory); //Call the mapper constructor

System.out.println("---------------- SAMPLE CLASS ------------- ");
SampleClass s1 = new SampleClass();
List<Map<String, String>> aField = new ArrayList<Map<String, String>>();
Map<String, String> map = new HashMap<>();
map.put("key1", "val1");
map.put("key2", "val2");
aField.add(map);
s1.setaField(aField);
s1.setbField("Sample text");

System.out.println("****** s1 contents ******");
System.out.println("--- s1 aField: " + ", list size: " + s1.getaField().size());
s1.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
System.out.println("--- s1 bField content: " + s1.getbField());
System.out.println("****** end of s1 contents ******");

SampleClass s2 = mapper.map(s1, SampleClass.class);
System.out.println("****** s2 contents ******");
System.out.println("--- s2 aField: " + ", list size: " + s2.getaField().size());
s2.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
System.out.println("--- s2 bField content: " + s2.getbField());
System.out.println("****** end of s2 contents ******");

System.out.println("---------------- SAMPLE CLASS ------------- ");
...

输出:

---------------- SAMPLE CLASS ------------- 
****** s1 contents ******
--- s1 aField: , list size: 1
key1:val1
key2:val2
--- s1 bField content: Sample text
****** end of s1 contents ******
****** s2 contents ******
--- s2 aField: , list size: 1
key1:val1
key2:val2
--- s2 bField content: Sample text
****** end of s2 contents ******
---------------- SAMPLE CLASS ------------- 

让我知道它是否有效。如果你有任何问题,请提问,我会尽力回答。如果这有效,请将答案标记为解决方案,以便其他有相同问题的人知道该怎么做。:)

 类似资料:
  • 我的班级等级如下: 并尝试将DTO映射到实体 地图如下: 我在详细信息字段中收到带有A或B的DTO,这是在调试器中检查的。但是模型制图者投掷 无法实例化目标组织的实例。包裹基础确保该组织。包裹Base有一个非私有的无参数构造函数。 我尝试使用显式提供程序(没有用于此映射): 我还尝试像这样实现自定义转换器(也没有执行): 模型映射器似乎没有对字段使用这个类型映射,只对hierarhy的根使用。在这

  • 问题内容: _id成员的类型仅从bson.ObjectId派生时,不再映射为ObjectId类型: id 在Mongo中应该是一个 _ObjectId 。但是事实证明,选择了 字符串 : Mongo Shell: 这可能是有意的,因为 bson.ObjectId 本身是从 string 派生的。但是在这里,这对我们不利。 我们可以告诉mgo将_id映射到数据库中的ObjectId吗? 问题答案:

  • 我有一个http:inbound-gateway,接收一个json消息,做一些充实,并使用http:outbound-gateway将它发送到一个endpoint,以调用一个同样具有json有效负载的rest服务。 入站gw接收内容类型标头,它设置在消息标头上,但当使用出站gw将有效负载发送到其余服务时,会发生以下错误:415不支持的媒体类型 我检查了日志,出现了以下警告: WARN Defaul

  • 当json更改为(小写命名与Java字段名相同)时工作正常: 但是,我需要在JSON中使用大写字段命名。 看起来不起作用。 是正确的映射吗?

  • 在我的项目中,我有一个有问题的表(这里名为),其中包含一些始终存在的列(在模式中定义,例如:),当应用程序运行时,会动态添加或删除其他列。我可以通过一个简单的函数使用这些“动态”列,该函数返回适当的对象: 该函数运行良好,我可以使用它返回的对象创建jOOQ查询。 当我想添加一个运行时映射,在呈现的查询中重命名这个有问题的表时,问题就开始了。 当我使用jOOQ创建一个简单的查询时,映射部分工作。 呈

  • 我必须通过ModelMapper将我从UI获得的DTO映射到我的实体。 在使用ModelMapper之前,我有以下方法: 在这种情况下,我必须通过LocalDateTime.now()生成新的LocalDateTime,并在两个不同的字段中使用它。 所以,我尝试这样配置ModelMapper: 它不起作用并不奇怪。我得到了NullPointerException。显然,在我试图获取关键字段的值时,