1. 前言
最近,自己在做一个天气预报Demo,其中利用到了
高德地图中的行政区域查询
接口—–通过url请求,返回相应的json数据,并将此数据转换为Java对象。主要是json数据的结构比较复杂,有json数组,而自己这方面的知识涉及得又比较少,所以,折腾了好长一段时间。
2. 需求分析
在Demo中,我是使用了高德地图中的天气预报接口,主要实现了两个功能:1. 根据城市id查询天气;2. 根据城市名称查询。奈何天气预报接口中没有根据城市名称查询天气,所以,我先通过行政区域查询接口把城市名称转换为城市id,再进行天气预报接口调用,这样就完成了上述功能。
由于接口中返回的都是json数据,为了方便客户端调用,需要把json数据转换为Java对象。
需要将以下的json数据转换为java对象:
3. 实战编码
将以上json数据抽象为两个java对象—–DistrictVO、DistrictResponseVO
DistrictVO:
@Data
public class DistrictVO implements Serializable {
private static final long serialVersionUID = 8444053771784412419L;
private List<String> citycode;
private String adcode;
private String name;
private String center;
private String level;
private List<DistrictVO> districts;
}
DistrictResponseVO:
@Data
public class DistrictResponseVO implements Serializable {
private static final long serialVersionUID = -5812661329615553770L;
private Integer status;
private Integer count;
private String info;
private Integer infocode;
private SuggestionVO suggestion;
private List<DistrictVO> districts;
}
JsonUtil:
public class JsonUtil {
public static DistrictResponseVO doGetDistrict(String json) throws Exception{
DistrictResponseVO districtResponseVO = new DistrictResponseVO();
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(json);
// 获取json字符串的值
String status = rootNode.get("status") != null ? rootNode.get("status").asText() : "";
String info = rootNode.get("info") != null ? rootNode.get("info").asText() : "";
String infocode = rootNode.get("infocode") != null ? rootNode.get("infocode").asText() : "";
String count = rootNode.get("count") != null ? rootNode.get("count").asText() : "";
districtResponseVO.setStatus(Integer.valueOf(status));
districtResponseVO.setInfo(info);
districtResponseVO.setInfocode(Integer.valueOf(infocode));
districtResponseVO.setCount(Integer.valueOf(count));
// 获取json数组的值----进行循环遍历
JsonNode provinceDistrictNode = rootNode.get("districts");
if (null != provinceDistrictNode && provinceDistrictNode.size() > 0) {
ArrayList<DistrictVO> districtList = new ArrayList<>();
for (JsonNode node : provinceDistrictNode) {
DistrictVO districtVO = new DistrictVO();
districtVO.setAdcode(node.get("adcode").asText());
districtVO.setName(node.get("name").asText());
districtVO.setCenter(node.get("center").asText());
districtVO.setLevel(node.get("level").asText());
JsonNode cityDistrictNode = node.get("districts");
List<DistrictVO> districtVOS = new ArrayList<>();
if (null != cityDistrictNode && cityDistrictNode.size() > 0) {
for (JsonNode jsonNode : cityDistrictNode) {
DistrictVO district = new DistrictVO();
district.setAdcode(jsonNode.get("adcode").asText());
district.setName(jsonNode.get("name").asText());
district.setCenter(jsonNode.get("center").asText());
district.setLevel(jsonNode.get("level").asText());
districtVOS.add(district);
}
}
districtVO.setDistricts(districtVOS);
districtList.add(districtVO);
}
districtResponseVO.setDistricts(districtList);
}
return districtResponseVO;
}
将java解析代码的过程对应如下图:
解析最外层结构(suggestion没解析)
解析省级结构
解析市级结构
main()
public static void main(String[] args) {
String str =
"{\"status\":\"1\",\"info\":\"OK\",\"infocode\":\"10000\",\"count\":\"1\","
+ "\"districts\":[{\"adcode\":\"370000\",\"name\":\"山东省\",\"center\":\"117.000923,36.675807\",\"level\":\"province\","
+ "\"districts\":[{\"adcode\":\"370600\",\"name\":\"烟台市\",\"center\":\"121.391382,37.539297\",\"level\":\"city\"},{\"adcode\":\"371000\",\"name\":\"威海市\",\"center\":\"122.116394,37.509691\",\"level\":\"city\"}]}]}";
try {
DistrictResponseVO districtResponseVO = JsonUtil.doGetDistrict(str);
System.out.println(districtResponseVO);
} catch (Exception e) {
e.printStackTrace();
}
}
使用main()方法进行测试
从我自身角度来看,Json数组解析过程其实并不复杂:首先得知道解析json的一些技术;其次,对于嵌套比较深的json数组,可以一层一层进行解析(画图的话,可能会更清晰)。
其实,对于第三方接口返回的数据,我们只需要根据返回的字段给自定义的java对象的属性一 一对应,然后在调用ObjectMapper.readValue()方法即可。如:
像这样的话,就可直接解析。至于对那个接口返回的数据为什么要进行手动解析,那是因为,返回的数据中存在着类似于“递归”的字段,这个,我也不会处理,所以,暂时就进行手动解析咯!!
【参考博主】
java使用jackson解析复杂json字符串