本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决
上文链接:
上文使用了单方法“ call() ”解决了List和基本类型(含String)以及对象的解析,但遗留了对象嵌套问题,本文将把 “ call() ” 方法中关于对象解析的部分拆分出独立的方法 “ analysisParam() ”,然后使用递归解决对象的嵌套问题
- /**
- * 调用远程过程
- */
- public Object call(DTGMM1020GERP paramEntity) {
- Object result = null;
- log.info("[PO创建时]入参:{}",JSON.toJSONString(paramEntity,true));
- Map map = JSONObject.parseObject(JSON.toJSONString(paramEntity, SerializerFeature.WriteDateUseDateFormat), Map.class);
- Map
wsdl = getWSDLContent(); - Client client = (Client) wsdl.get("client");
- List
partInfos = (List) wsdl.get("messagePartInfo"); - QName qName = (QName) wsdl.get("qname");
-
- String clazzName = partInfos.get(0).getTypeClass().getName();
- try {
- Object requestParamObject = Thread.currentThread().getContextClassLoader().loadClass(clazzName).newInstance();
- requestParamObject = analysisParam(requestParamObject,map);
- log.info("请求参数:{}",JSON.toJSON(requestParamObject));
- result = client.invoke(qName, requestParamObject);
- log.info("响应结果:{}",JSON.toJSONString(result,true));
- } catch (Exception e) {
- e.printStackTrace();
- }
- return result;
- }
解说:方法 “ call() ” 接收一个 “ DTGMM1020GERP ” 对象作为入参并返回一个Object对象,该方法主要业务就是将入参对象转换成map对象,而后读取WSDL文件内容,并传入给 “ analysisParam() ” 方法解析,其中requestParamObject是读出的WSDL文件的节点,map是待写入节点的值
- private static Object analysisParam(Object req, Map map) throws InstantiationException, IllegalAccessException {
- Field[] fields = req.getClass().getDeclaredFields();
- for (Field field : fields) {
- field.setAccessible(true);
- boolean b = field.getGenericType() instanceof ParameterizedType;
- //如果是泛型并且是List类型
- if(b && field.getType() == List.class){
- List> cParam = (List>) map.get(field.getName());
- log.info("子对象参数:{}",cParam);
- if(CollectionUtils.isEmpty(cParam)){
- continue;
- }
- Type type = ((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0];
- Class> aClass = (Class>) type;
- Object cObj = aClass.newInstance();
- log.info("子对象:{}",cObj);
-
- Field[] cFields = cObj.getClass().getDeclaredFields();
- for (Field cField : cFields) {
- cField.setAccessible(true);
- List> target = cParam.stream().map(o -> {
- Map ccParam = JSONObject.parseObject(JSON.toJSONString(o),Map.class);
- Object strParam = ccParam.get(cField.getName());
- //如果子对象类型是基本类型或String类型那就直接赋值,负责就递归
- if(cField.getType().isPrimitive() || cField.getType() == String.class){
- try {
- if(null != strParam){
- cField.set(cObj,strParam);
- }
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }else{
- try {
- Object obj = cField.getType().newInstance();
- Map objMap = JSONObject.parseObject(JSON.toJSONString(strParam),Map.class);
- if(!CollectionUtils.isEmpty(objMap)){
- analysisParam(obj,objMap);
- cField.set(cObj,obj);
- }
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- return strParam;
- }).collect(Collectors.toList());
- /*Object targetResp = target.get(0);
- cField.set(cObj,targetResp);*/
- }
- List
- cObjs.add(cObj);
- //给父对象赋值
- field.set(req,cObjs);
- }else if(field.getType().isPrimitive() || field.getType() == String.class){
- //如果是基本类型或String类型
- field.set(req,map.get(field.getName()));
- }else{
- //按对象处理
- Object o = field.getType().newInstance();
- Map childrenObjMap = (Map) map.get(field.getName());
- if(!CollectionUtils.isEmpty(childrenObjMap)){
- writeFieldValue(o,childrenObjMap);
- field.set(req,o);
- }
- }
- }
- return req;
- }
一、使用反射获取待解析节点的字段
二、进行第一层 for 循环解析节点,先判断了字段的类型是否为泛型且为List类型,如果不是泛型且不是List类型,再判断是否为基本类型或是String类型,如果也不是,那就当成普通对象处理
三、如果第一层 for 循环中的类型为泛型且为List类型时,则进行第二层 for 循环处理,第二层循环同样判断子对象字段值是否为基本类型或String类型,如果是则直接赋值,如果不是,则说明是一个对象,至于是个什么对象(List?基本类型?String?POJO?),无需理会,直接进行递归解析即可
本文中引用到的其他方法请从上一篇文章中获取
这是我mock加数据的方法,入参对象可以使用该方法快速生成mock数据(本文中的DTGMM1020GERP )
- public static
T getEntityData(T t) { - Field[] field = t.getClass().getDeclaredFields();
- for (Field f : field) {
- f.setAccessible(true);
- try {
- Random random = new Random();
- int num = random.nextInt(10);
- f.set(t,""+num);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- return t;
- }
只需要定义好对象的嵌套层级即可
- List
list = new ArrayList<>(); - DTGMM1020GERP entity = new DTGMM1020GERP();
- entity = getEntityData(entity);
- list.add(entity);
