1.问题:
业务需要把第三方接口的带下划线的字段规范为驼峰的字段
第三方接口的bean对象:
public class ObjectsDetail extends XMLElementData implements Serializable {
private static final long serialVersionUID = 5080447582610246168L;
private String objectclass;
private String view_guid;
private String group_guid;
private String user_guid;
private String all_path_name;
private String original_sort;
}
要转换为驼峰的本地对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class H4aUsers {
private String objectclass;
private String viewGuid;
private String groupGuid;
private String userGuid;
private String allPathName;
private String originalSort;
}
2.解决思路
2.1 使用自带的BidirectionalConverter接口
发现只能同字段名称不同字段类型转换,像String转Date,list转String
参考博客http://www.lxiaoyu.com/p/283285
2.2 使用orika自带的field方法实现
传入一个map对象即可
/**
* Map a field in both directions
*
* @param fieldNameA
* property name in type A
* @param fieldNameB
* property name in type B
* @return
*/
public ClassMapBuilder<A, B> field(String fieldNameA, String fieldNameB) {
return fieldMap(fieldNameA, fieldNameB).add();
}
2.2.1 使用hutool的反射工具获取两个对象的所有字段
使用CharSequenceUtil.toCamelCase()
方法把下划线转驼峰字段判断,然后映射到map集合返回
public Map<String, String> getCamelCaseMap(Class<?> source, Class<?> des) {
//带下划线的实体类字段集合
Field[] sourceFields = ReflectUtil.getFields(source);
log.info("getCamelCaseMap sourceFields = " + sourceFields.length);
//带驼峰的实体类字段集合
Field[] desFields = ReflectUtil.getFields(des);
log.info("getCamelCaseMap desFields = " + desFields.length);
//只获取字段名集合
List<String> sources = Arrays.stream(sourceFields).map(Field::getName).collect(Collectors.toList());
Map<String, String> fieldsMap = Maps.newHashMap();
//遍历驼峰字段集合
for (Field desField : desFields) {
String name = desField.getName();
//判断是否和转换后的字段相同
Optional<String> first = sources.stream().filter(s -> Objects.equals(CharSequenceUtil.toCamelCase(s), name)).findFirst();
//相同则放入map映射
if (first.isPresent()) {
fieldsMap.put(first.get(), name);
}else {
log.info("getCamelCaseMap name = " + name);
}
}
log.info("getCamelCaseMap fieldsMap = " + fieldsMap.size());
return fieldsMap;
}
2.2.2 把获取的map传给orika
/**
* 获取自定义映射
*
* @param toClass 映射类
* @param dataClass 数据映射类
* @param configMap 自定义配置
* @param useDefaultMap 是否使用默认映射
* @return 映射类对象
*/
private <E, T> MapperFacade getMapperFacade(Class<E> toClass, Class<T> dataClass, Map<String, String> configMap, List<CustomConverter<?, ?>> converter, boolean useDefaultMap) {
String mapKey = dataClass.getCanonicalName() + "_" + toClass.getCanonicalName();
MapperFacade mapperFacade = CACHE_MAPPER_FACADE_MAP.get(mapKey);
if (Objects.isNull(mapperFacade)) {
MapperFactory factory = new DefaultMapperFactory.Builder().build();
if (!converter.isEmpty()) {
converter.forEach(con -> factory.getConverterFactory().registerConverter(con));
}
ClassMapBuilder classMapBuilder = factory.classMap(dataClass, toClass);
//映射不同字段名的实体
if (CollUtil.isNotEmpty(configMap)) {
configMap.forEach(classMapBuilder::field);
}
if (useDefaultMap) {
classMapBuilder.byDefault();
}
classMapBuilder.register();
mapperFacade = factory.getMapperFacade();
CACHE_MAPPER_FACADE_MAP.put(mapKey, mapperFacade);
}
return mapperFacade;
}
/**
* 映射实体(自定义配置)
*
* @param toClass 映射类对象
* @param data 数据(对象)
* @param configMap 自定义配置
* @return 映射类对象
*/
public <E, T> E map(Class<E> toClass, T data, Map<String, String> configMap) {
MapperFacade mapperFacade = this.getMapperFacade(toClass, data.getClass(), configMap, new ArrayList<>(), true);
return mapperFacade.map(data, toClass);
}
2.2.3 测试
@Test
public void testCamlCase() {
ObjectsDetail objectsDetail = new ObjectsDetail();
objectsDetail.setOrg_class("1111");
objectsDetail.setOrg_guid("2222");
objectsDetail.setObjectclass("33333");
objectsDetail.setView_guid("4444");
objectsDetail.setUser_guid("5555");
objectsDetail.setAll_path_name("666666");
objectsDetail.setOriginal_sort("7777");
Map<String, String> camelCaseMap = OrikaTool.getInstance().getCamelCaseMap(ObjectsDetail.class, H4aUsers.class);
H4aUsers map = OrikaTool.getInstance().map(H4aUsers.class, objectsDetail, camelCaseMap);
System.out.println("map = " + map);
}
3.注意
转驼峰的实体一定要实现无参构造和有参构造,orika是根据构造方法获取参数去映射的
@Data
@NoArgsConstructor
@AllArgsConstructor
public class H4aUsers {}