解析JsonObject的数据结构(一)

       最近在对接一个第三方接口时碰到这样的一种数据结构,刚开始全部对接完成的时候,发现里面没有一丝嵌套,不需要采用数组啥的,心里还挺赞叹他们的接口,,结果,昨天领导说需要拿到里面的某个字段,计算后放回原地方。这才深刻体会到这种数据结构的难受之处。

       首先先上代码,会发现就是一个很平常的json结构。

{
  "rcode": "000000",
  "desc": "请求成功",
  "data": {
    "didi": {
      "estimate_price": {
        "favourable": false,
        "price": 36.9,
        "name": "普通型",
        "memo": "",
        "real_price": 36.9
      },
      "min_duration": {
        "has_car": true,
        "min_distance": 2298,
        "min_duration": 7
      }
    },
    "yidao": {
      "estimate_price": {
        "favourable": false,
        "price": 54,
        "name": "易达",
        "memo": "",
        "real_price": 54
      },
      "min_duration": {
        "has_car": false,
        "min_duration": 4
      }
    },
    "caocao": {
      "estimate_price": {
        "favourable": true,
        "price": 375.9,
        "name": "新能源",
        "memo": "限时9.8折",
        "real_price": 368.402
      },
      "min_duration": {
        "has_car": false,
        "min_duration": 8
      }
    }
  }
}

着眼望去,key--value,key--value......说实话,我刚开始是有点无从下手的,这种形式如果嵌套很多层,压根无法循环解析,因为里面永远有key存在,你怎么解析呢?

在这里提一下我需要实现的功能:拿出每一个供应商下的price字段,调用本地接口查询出手续费,将手续费加上去,最后塞回到相应的位置。

最终我的思路是这样的,首先遍历出所有的供应商key,由于只有供应商是不同的,里面的结构体是一样的。那么我就抽出所有不同供应商的结构体再做处理。

 //拿到data结构下的数据     
 JSONObject jsons = JSONObject.parseObject(res.getString("data"));
 List list = new ArrayList();
 //遍历data结构下的所有数据,这一点和map是一致的
 Set<Map.Entry<String, Object>> entries = jsons.entrySet();
 JSONObject o1 = new JSONObject();
 //循环遍历,有几个供应商就循环几次
 for (Map.Entry<String, Object> temp : entries) {
 //注意此处,我只拿出了当前循环中的value值,然后进一步拿出想要的estimate_price,
 //因为需要的字段就在这个结构体里面,放入到list集合中
 JSONObject o = (JSONObject) temp.getValue();
 o1 = JSONObject.parseObject(o.getString("estimate_price"));
 list.add(o1.getString("price"));
 log.info(o.toJSONString());
        }

最终你会拿到相应供应商的price字段下面的值。

这个时候已经拿出相应的price值,下一步请求本地接口查询手续费,这里是我本地的事情,我就基本略过。不过我这里接口拿到的值是key,key,key,的形式。所以也间接加强了后面塞值的难度。

 //拿到相应参数去获取手续费
 StringBuilder builder = new StringBuilder();
 //此处采用stringbuilder是为了避免循环只拿到一个值
 for (int i = 0; i < list.size(); i++) {
     builder.append(list.get(i) + ",");
 }
 //本地为key,key,的形式,处理最后一个逗号
 String amount = builder.substring(0, builder.length() - 1);
 String urls = baseServer + "query/fee";
 Map<String, Object> maps = new HashMap<>();
 maps.put("customNo", customerNo);
 maps.put("orderType", ApiConstants.CommonOrderType.ORDER_TYPE_FUEL_CARD_CAOCAO);
 maps.put("amount", amount);
 JSONObject json = JSONObject.parseObject(post(urls, maps));
 JSONObject addjson = JSONObject.parseObject(json.getString("data"));
 String prices = addjson.getString("fee");
 //返回相应的手续费,用逗号隔开,所以在这里就需要解析掉逗号
 String[] strs = prices.split(",");
 //这里的jsons代表的就是之前的data结构体,只不过此处我遍历的是key,而不是所有数据
 Set<String> keyset = jsons.keySet();
 //声明一个迭代器去迭代里面的数据
 Iterator<String> it = keyset.iterator();
 //此处的strs代表的是解析后的手续费数组,这里接口返回的是我传过去的值的对应值,不需要考虑乱序问题
 for (String str : strs) {
 //判断迭代器是否存在值
      while (it.hasNext()) {
 //拿到迭代器中的传进来的数据,例如didi,caocao,shenzhou等供应商,根据这个去解析data中的数据
           String keystr = it.next();
 //以下两行代码解析到供应商下的estimate_price结构
           JSONObject k1 = JSONObject.parseObject(jsons.getString(keystr));
           JSONObject k2 = JSONObject.parseObject(k1.getString("estimate_price"));
 //这里就是需要对price进行重新赋值,类似map直接put即可,注意格式
                k2.put("price", new BigDecimal(k2.getString("price")).add(new 
 BigDecimal(str)));
 //同上直接赋值(业务需要)
                k2.put("real_price", new BigDecimal(k2.getString("real_price")).add(new 
 BigDecimal(str)));
 //有点像map中的putAll()方法,将修改的值放回estimate_price中
                k1.put("estimate_price", k2);
 //将estiamte_price放回到供应商下,也就是keyStr下面
                jsons.put(keystr, k1);
 //跳出,执行下一个供应商
                break;
            }
        }
 //最后将更新后的值返回到前台,ok啦。
  return BaseResponse.success(jsons);

说实话,这里的重新赋值我弄了好一会,因为我最开始的考虑是为了避免重复赋值,是想删除set集合中的数据的。结果发现直接用迭代器他是直接会循环的,而外面那一层的手续费循环已经结束,所以也就不用考虑重复问题了。

还是需要多用下这个迭代器和集合的操作,不同的方式可以发现你自身更多的问题。

猜你喜欢

转载自blog.csdn.net/T_james/article/details/81201342
今日推荐