我有jaxb生成的数据结构。部分结构基本相同,但它们位于不同的名称空间中,因此生成的Java类型不同。
我需要在这些结构之间传输数据。在项目中,ModelMapper用于映射,所以我希望使用它。
我的问题是ModelMapper无法映射为'maxOccurs="unb界"元素生成的列表。
假设我有以下模式:
<xs:complexType name="CityData">
<xs:sequence>
<xs:element name="districtData" type="DistrictData" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="DistrictData">
<xs:sequence>
<xs:element name="population" type="xs:int" nillable="false" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
我在namespacea和namespaceb中都有这个模式,因此Jaxb将以下类型生成到包namespacea和包namespaceb中:
public class CityData {
@XmlElement(required = true)
protected List<DistrictData> districtData;
//... jaxb explanation why there's no setter
public List<DistrictData> getDistrictData() {
if (districtData == null) {
districtData = new ArrayList<DistrictData>();
}
return this.districtData;
}
}
public class DistrictData {
protected int population;
public int getPopulation() {
return population;
}
public void setPopulation(int value) {
this.population = value;
}
}
现在,如果我从程序包namespacea创建一个源CityData,并要求modelmapper将其映射到namespaceb中的目标CityData,则数据不会被映射:
CityData cityData = new CityData();
DistrictData districtData = new DistrictData();
districtData.setPopulation(1234);
cityData.getDistrictData().add(districtData);
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
namespaceb.CityData dest = modelMapper.map(cityData, namespaceb.CityData.class);
System.out.println("dest.districtData: " + dest.getDistrictData());
结果是:
dest.districtData: []
换句话说,districtData不会复制到目标。
我知道ModelMapper没有为districtData找到setter,因此没有对其进行映射。我了解到,可以重新配置Jaxb以生成列表属性的setter,但Jaxb对象生成并不在我的项目中。
因此,我想知道是否有一个很好的解决方案,可以使用ModelMapper进行映射,或者在这些情况下使用其他映射器库。
我创建了一个小项目:https://github.com/riskop/ModelMapperJaxb
我对ModelMapper的笨拙解决方法有一个粗略的想法。在阅读pirho的答案之前,转换设施。我认为皮罗的答案更好(被接受),但作为记录,下面是转换器的解决方法。这基本上是在没有设置器的情况下手动定义子结构的转换:
CountryData countryData = new CountryData();
CityData cityData = new CityData();
DistrictData districtData = new DistrictData();
districtData.setPopulation(1234);
cityData.getDistrictData().add(districtData);
countryData.getCityData().add(cityData);
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
modelMapper.addConverter(new Converter<CountryData, namespaceb.CountryData>() {
@Override
public namespaceb.CountryData convert(MappingContext<CountryData, namespaceb.CountryData> context) {
namespaceb.CountryData result = new namespaceb.CountryData();
if(context.getSource() != null) {
for(CityData cityData : context.getSource().getCityData()) {
namespaceb.CityData mapped = modelMapper.map(cityData, namespaceb.CityData.class);
result.getCityData().add(mapped);
}
}
return result;
}
});
modelMapper.addConverter(new Converter<CityData, namespaceb.CityData>() {
@Override
public namespaceb.CityData convert(MappingContext<CityData, namespaceb.CityData> context) {
namespaceb.CityData result = new namespaceb.CityData();
if(context.getSource() != null) {
for(DistrictData districtData : context.getSource().getDistrictData()) {
namespaceb.DistrictData mapped = modelMapper.map(districtData, namespaceb.DistrictData.class);
result.getDistrictData().add(mapped);
}
}
return result;
}
});
namespaceb.CountryData destCountryData = modelMapper.map(countryData, namespaceb.CountryData.class);
assertEquals(1, destCountryData.getCityData().size());
namespaceb.CityData destCityData = destCountryData.getCityData().get(0);
assertEquals(1, destCityData.getDistrictData().size());
namespaceb.DistrictData destDistrictData = destCityData.getDistrictData().get(0);
assertEquals(1234, destDistrictData.getPopulation());
我认为您只需要启用字段匹配,并将字段的访问级别设置为匹配,以处理缺少的setter。检查此配置:
modelMapper.getConfiguration()
.setMatchingStrategy(MatchingStrategies.STRICT)
.setFieldMatchingEnabled(true)
.setFieldAccessLevel(AccessLevel.PROTECTED);
Javadoc:
setFieldAccessEnabled
设置是否应启用字段匹配。如果为true,则可以在可访问字段之间进行映射。默认值为false。
setFieldAccessLevel
指示字段应符合给定访问级别的匹配条件
注意:字段访问仅在启用字段匹配时使用。
我的班级等级如下: 并尝试将DTO映射到实体 地图如下: 我在详细信息字段中收到带有A或B的DTO,这是在调试器中检查的。但是模型制图者投掷 无法实例化目标组织的实例。包裹基础确保该组织。包裹Base有一个非私有的无参数构造函数。 我尝试使用显式提供程序(没有用于此映射): 我还尝试像这样实现自定义转换器(也没有执行): 模型映射器似乎没有对字段使用这个类型映射,只对hierarhy的根使用。在这
我正在尝试使用ModelMapper映射对象树。 我创建了一个例子来说明我的问题: 类包含多个属性 类包含类型为Sub的对象和(至少)另一个属性 类目标包含一个简单的属性列表 源属性和目标属性的类型不同 代码: 我正在寻找一种配置单个ModelMapper实例的方法,以便满足以下约束: modelMapper能够将Sub类型的对象转换为目标对象 不幸的是,行<代码>映射(source.sub,de
我与ModelMapper框架有麻烦。请解释为什么我看到以下行为。 我在build.gradle有以下依赖性 和一个类客户: 我还有一个地图绘制工具: 还有一个测试 在fred()中,方法输出是非红色的“Customer{name=fred,age=40}”(“Customer{name=null,age=40}”)。你能解释一下为什么吗?为什么我在第一个方法中看不到输出“George”?
首先,我有下面的发票清单。每个列表对象都有一个零件号、一个描述、数量和一个价格。 我将其映射到数量上,并将其排序到数量上,得到以下结果: 但是我如何在上进行映射,以便在我的结果中显示在所显示的数量前面?我不能这样做:
问题内容: 我正在尝试整理实现公共接口的对象列表。涉及3个类和1个接口: 社区 类(具有一种方法: List getPeople(); ) 人员 接口(具有一种方法: String getName(); ) 女生 班(实施人员) 男生 班(实施人员) 请参见下面的代码。 我想要一个看起来像这样的XML: 或可能: 到目前为止,我得到的是: 我意识到我可以将元素更改为其他名称,但是我希望元素名称成为