Gson解析复杂的Json数据(反序列化)
一、准备工作
需要Gson的Jar包:
二、代码实现
1、复杂的Json数据
{
"type": "FeatureCollection",
"metadata": {
"generated": 1587342592000,
"url": "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&limit=10&minmag=6&orderby=time",
"title": "USGS Earthquakes",
"status": 200,
"api": "1.8.1",
"limit": 10,
"offset": 1,
"count": 9
},
"features": [{
"type": "Feature",
"properties": {
"mag": 6.2999999999999998,
"place": "25km SE of Ofunato, Japan",
"time": 1587328745984,
"updated": 1587341149813,
"tz": 540,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us7000903m",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us7000903m&format=geojson",
"felt": 49,
"cdi": 4.5999999999999996,
"mmi": 5.5709999999999997,
"alert": "green",
"status": "reviewed",
"tsunami": 0,
"sig": 633,
"net": "us",
"code": "7000903m",
"ids": ",us7000903m,pt20110001,at00q91yp4,",
"sources": ",us,pt,at,",
"types": ",dyfi,geoserve,ground-failure,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 1.99,
"rms": 1.1399999999999999,
"gap": 39,
"magType": "mww",
"type": "earthquake",
"title": "M 6.3 - 25km SE of Ofunato, Japan"
},
"geometry": {
"type": "Point",
"coordinates": [141.93180000000001, 38.911900000000003, 38]
},
"id": "us7000903m"
},
{
"type": "Feature",
"properties": {
"mag": 6.5999999999999996,
"place": "209km W of Chichi-shima, Japan",
"time": 1587198337201,
"updated": 1587329781823,
"tz": 540,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008z89",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008z89&format=geojson",
"felt": 40,
"cdi": 3.7999999999999998,
"mmi": 0,
"alert": "green",
"status": "reviewed",
"tsunami": 1,
"sig": 685,
"net": "us",
"code": "70008z89",
"ids": ",at00q8z62q,pt20109000,us70008z89,",
"sources": ",at,pt,us,",
"types": ",dyfi,geoserve,impact-link,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 1.853,
"rms": 0.75,
"gap": 34,
"magType": "mww",
"type": "earthquake",
"title": "M 6.6 - 209km W of Chichi-shima, Japan"
},
"geometry": {
"type": "Point",
"coordinates": [140.1061, 27.139800000000001, 453.76999999999998]
},
"id": "us70008z89"
},
{
"type": "Feature",
"properties": {
"mag": 6,
"place": "55km NNE of Savannah Bight, Honduras",
"time": 1587024277597,
"updated": 1587311760245,
"tz": -360,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008xeb",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008xeb&format=geojson",
"felt": 134,
"cdi": 5.5,
"mmi": 4.6470000000000002,
"alert": "green",
"status": "reviewed",
"tsunami": 1,
"sig": 628,
"net": "us",
"code": "70008xeb",
"ids": ",at00q8vfrr,pt20107000,us70008xeb,",
"sources": ",at,pt,us,",
"types": ",dyfi,geoserve,ground-failure,impact-link,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 3.323,
"rms": 1.45,
"gap": 31,
"magType": "mww",
"type": "earthquake",
"title": "M 6.0 - 55km NNE of Savannah Bight, Honduras"
},
"geometry": {
"type": "Point",
"coordinates": [-85.709900000000005, 16.933199999999999, 10]
},
"id": "us70008xeb"
},
{
"type": "Feature",
"properties": {
"mag": 6,
"place": "194km SE of Raoul Island, New Zealand",
"time": 1586826407913,
"updated": 1586912943507,
"tz": -720,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008vsp",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008vsp&format=geojson",
"felt": 1,
"cdi": 1,
"mmi": 0,
"alert": "green",
"status": "reviewed",
"tsunami": 0,
"sig": 554,
"net": "us",
"code": "70008vsp",
"ids": ",us70008vsp,at00q8r731,pt20105000,",
"sources": ",us,at,pt,",
"types": ",dyfi,geoserve,ground-failure,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 1.7849999999999999,
"rms": 0.70999999999999996,
"gap": 14,
"magType": "mww",
"type": "earthquake",
"title": "M 6.0 - 194km SE of Raoul Island, New Zealand"
},
"geometry": {
"type": "Point",
"coordinates": [-176.34780000000001, -30.3889, 31]
},
"id": "us70008vsp"
},
{
"type": "Feature",
"properties": {
"mag": 6.0999999999999996,
"place": "96km N of Amsterdam Island, France",
"time": 1586674667719,
"updated": 1586811032040,
"tz": 300,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008um8",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008um8&format=geojson",
"felt": null,
"cdi": null,
"mmi": 4.242,
"alert": "green",
"status": "reviewed",
"tsunami": 0,
"sig": 572,
"net": "us",
"code": "70008um8",
"ids": ",us70008um8,pt20103000,at00q8ny0e,",
"sources": ",us,pt,at,",
"types": ",geoserve,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 0.83599999999999997,
"rms": 0.91000000000000003,
"gap": 32,
"magType": "mww",
"type": "earthquake",
"title": "M 6.1 - 96km N of Amsterdam Island, France"
},
"geometry": {
"type": "Point",
"coordinates": [77.445899999999995, -36.963700000000003, 10]
},
"id": "us70008um8"
},
{
"type": "Feature",
"properties": {
"mag": 6.5,
"place": "72km W of Challis, Idaho",
"time": 1585698751094,
"updated": 1587340955674,
"tz": -420,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008jr5",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008jr5&format=geojson",
"felt": 39139,
"cdi": 7.5999999999999996,
"mmi": 8.2390000000000008,
"alert": "green",
"status": "reviewed",
"tsunami": 0,
"sig": 1410,
"net": "us",
"code": "70008jr5",
"ids": ",us70008jr5,mb80387294,pt20091001,at00q830zi,uu60371877,",
"sources": ",us,mb,pt,at,uu,",
"types": ",dyfi,finite-fault,general-link,general-text,geoserve,ground-failure,impact-text,internal-origin,losspager,moment-tensor,oaf,origin,phase-data,shakemap,",
"nst": null,
"dmin": 0.879,
"rms": 0.68000000000000005,
"gap": 31,
"magType": "mww",
"type": "earthquake",
"title": "M 6.5 - 72km W of Challis, Idaho"
},
"geometry": {
"type": "Point",
"coordinates": [-115.1356, 44.460299999999997, 14.529999999999999]
},
"id": "us70008jr5"
},
{
"type": "Feature",
"properties": {
"mag": 6.0999999999999996,
"place": "27km SW of Baliton, Philippines",
"time": 1585237084150,
"updated": 1585407221588,
"tz": 480,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008ghw",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008ghw&format=geojson",
"felt": 24,
"cdi": 5.7000000000000002,
"mmi": 5.6310000000000002,
"alert": "green",
"status": "reviewed",
"tsunami": 0,
"sig": 586,
"net": "us",
"code": "70008ghw",
"ids": ",us70008ghw,pt20086000,",
"sources": ",us,pt,",
"types": ",dyfi,geoserve,ground-failure,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 1.5740000000000001,
"rms": 1.3200000000000001,
"gap": 11,
"magType": "mww",
"type": "earthquake",
"title": "M 6.1 - 27km SW of Baliton, Philippines"
},
"geometry": {
"type": "Point",
"coordinates": [125.0531, 5.5753000000000004, 59]
},
"id": "us70008ghw"
},
{
"type": "Feature",
"properties": {
"mag": 7.5,
"place": "221km SSE of Severo-Kuril'sk, Russia",
"time": 1585104560896,
"updated": 1586394371534,
"tz": 660,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008fi4",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008fi4&format=geojson",
"felt": 27,
"cdi": 5.5999999999999996,
"mmi": 5.2460000000000004,
"alert": "green",
"status": "reviewed",
"tsunami": 1,
"sig": 881,
"net": "us",
"code": "70008fi4",
"ids": ",at00q7qai7,pt20085000,us70008fi4,",
"sources": ",at,pt,us,",
"types": ",dyfi,finite-fault,general-text,geoserve,ground-failure,impact-link,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 4.1040000000000001,
"rms": 0.67000000000000004,
"gap": 12,
"magType": "mww",
"type": "earthquake",
"title": "M 7.5 - 221km SSE of Severo-Kuril'sk, Russia"
},
"geometry": {
"type": "Point",
"coordinates": [157.69139999999999, 48.968800000000002, 55.390000000000001]
},
"id": "us70008fi4"
},
{
"type": "Feature",
"properties": {
"mag": 6.0999999999999996,
"place": "Central East Pacific Rise",
"time": 1584916684810,
"updated": 1586121707611,
"tz": -420,
"url": "https://earthquake.usgs.gov/earthquakes/eventpage/us70008e91",
"detail": "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70008e91&format=geojson",
"felt": null,
"cdi": null,
"mmi": 0,
"alert": "green",
"status": "reviewed",
"tsunami": 0,
"sig": 572,
"net": "us",
"code": "70008e91",
"ids": ",us70008e91,pt20082002,at00q7m9jj,",
"sources": ",us,pt,at,",
"types": ",geoserve,internal-origin,losspager,moment-tensor,origin,phase-data,shakemap,",
"nst": null,
"dmin": 22.978000000000002,
"rms": 0.68000000000000005,
"gap": 53,
"magType": "mww",
"type": "earthquake",
"title": "M 6.1 - Central East Pacific Rise"
},
"geometry": {
"type": "Point",
"coordinates": [-104.95189999999999, -4.6744000000000003, 10]
},
"id": "us70008e91"
}
],
"bbox": [-176.3478, -36.9637, 10, 157.6914, 48.9688, 453.77]
}
2、后端代码实现
这个json可以说是相当的复杂,对象里有数组,数组里有对象,而我们要获得地震的等级、地点、时间、url是在features数组里的properties中的部分数据。
如果我们按照常规的方法用Gson将Json转换为Javabean的对象,我们要创建多个Javabean对象,并且要将Json里的每个数据都要和类里的对象一一对应,在有几百上千条数据的Json里这是不切实际的。比如这个Json就要创建三个Javabean,相当复杂。
而简便的从Json中拿到我们需要的等级、地点、时间、url,我们可以灵活的运用List<>()、Map(),这里只需要创建一个Javabean代码如下:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.lsq.earth;
/**
*
* @author 刘
*/
public class Properties {
private double mag;
private String place;
private String time;
private String url;
public Properties(double mag, String place, String time, String url) {
this.mag = mag;
this.place = place;
this.time = time;
this.url = url;
}
public double getMag() {
return mag;
}
public void setMag(double mag) {
this.mag = mag;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
使用Gson反序列化Json
public List<Properties> getProperties() {
List<Properties> list = new ArrayList<>();
try {
//获取json数据,makeHttpRequest()是自己编写的从网络获取Json的方法。
URL url = new URL(USGS_REQUEST_URL + "?format=geojson&limit=10&minmag=6&orderby=time");
String response = makeHttpRequest(url);
//将json反序列化成Map
Gson gson = new Gson();
Map map = gson.fromJson(response, Map.class);
List<Map> features = (List<Map>) map.get("features");
//设置时间的格式为yyyy-MM-dd HH:mm:ss
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//遍历获取你要的数据,添加到Javabean对象里
for (Map m : features) {
Map propertiesMap = (Map) m.get("properties");
double mag = (double) propertiesMap.get("mag");
String place = (String) propertiesMap.get("place");
long time = ((Double) propertiesMap.get("time")).longValue();
String timeStr = sdf.format(new Date(time));
String Url = (String) propertiesMap.get("url");
list.add(new Properties(mag, place, timeStr, Url));
}
} catch (MalformedURLException ex) {
java.util.logging.Logger.getLogger(GetEarthData4s.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
java.util.logging.Logger.getLogger(GetEarthData4s.class.getName()).log(Level.SEVERE, null, ex);
}
return list;
}
这样我们就可以简便的从复杂的Json数据里剔除不必要的数据,获取我们想要的数据了。
这里给上如何从网络获取Json数据的代码:
package org.dusin.gson.excises;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.logging.Level;
import org.apache.log4j.Logger;
/**
*
* @author dusin
*/
public class GetEarthData4s {
static Logger logger = Logger.getLogger(GetEarthData4s.class.getName());
public static final String USGS_REQUEST_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query";
public static void main(String[] args){
try {
URL url = new URL(USGS_REQUEST_URL+"?format=geojson&limit=10&minmag=6&orderby=time");
String response = makeHttpRequest(url);
System.out.println(response);
} catch (MalformedURLException ex) {
java.util.logging.Logger.getLogger(GetEarthData4s.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
java.util.logging.Logger.getLogger(GetEarthData4s.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Make an HTTP request to the given URL and return a String as the response.
*/
public static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
logger.error( "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
logger.error("Problem retrieving the earthquake JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// Closing the input stream could throw an IOException, which is why
// the makeHttpRequest(URL url) method signature specifies than an IOException
// could be thrown.
inputStream.close();
}
}
return jsonResponse;
}
private static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
}
3、前端代码实现
<%@page import="com.lsq.earth.GetEarthData4s"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="java.util.*"%>
<%@page import="com.lsq.earth.Properties"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<%
GetEarthData4s earth = new GetEarthData4s();
List<Properties> list = earth.getProperties();
%>
<table align="center" border="1" cellpadding="6">
<tr>
<td>震级</td><td>地点</td><td>时间</td><td>url</td>
</tr>
<% for (Properties b : list) {
out.println("<tr><td/>" + b.getMag() + "</td><td>" + b.getPlace()
+ "</td><td>" + b.getTime() + "</td><td><a href=" + b.getUrl() + ">" + b.getUrl()
+ "</a></td>");
}
%>
</table>
</body>
</html>
三、效果图
以后遇到这种复杂的Json,不要再傻傻地去创建多个bean了,我们可以将Json暂存在List、Map中,灵活的运用Gson。