java - 使用 gson 解析 JSON - 解析时套接字关闭
问题描述
我尝试使用 gson 在此代码段中解析 JSON:
{
"cod":"200",
"message":0,
"cnt":40,
"list":[
{"dt":1584565200,"main":{"temp":284.22,"feels_like":279.95,"temp_min":282.33,"temp_max":284.22,"pressure":1021,"sea_level":1021,"grnd_level":1011,"humidity":81,"temp_kf":1.89},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":100},"wind":{"speed":5.42,"deg":275},"sys":{"pod":"n"},"dt_txt":"2020-03-18 21:00:00"},
{"dt":1584576000,"main":{"temp":282.97,"feels_like":279.59,"temp_min":281.55,"temp_max":282.97,"pressure":1021,"sea_level":1021,"grnd_level":1011,"humidity":88,"temp_kf":1.42},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":4.14,"deg":273},"rain":{"3h":0.44},"sys":{"pod":"n"},"dt_txt":"2020-03-19 00:00:00"},
{"dt":1584586800,"main":{"temp":281.44,"feels_like":277.55,"temp_min":280.5,"temp_max":281.44,"pressure":1020,"sea_level":1020,"grnd_level":1010,"humidity":87,"temp_kf":0.94},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],"clouds":{"all":100},"wind":{"speed":4.33,"deg":286},"rain":{"3h":0.81},"sys":{"pod":"n"},"dt_txt":"2020-03-19 03:00:00"},
{"dt":1584597600,"main":{"temp":279.82,"feels_like":276.13,"temp_min":279.35,"temp_max":279.82,"pressure":1021,"sea_level":1021,"grnd_level":1011,"humidity":89,"temp_kf":0.47},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"clouds":{"all":100},"wind":{"speed":3.66,"deg":311},"rain":{"3h":0.56},"sys":{"pod":"d"},"dt_txt":"2020-03-19 06:00:00"}]
实际上它要长得多,大约有 15,000 个字符。我需要的只是温度、dts、雨或雪降水,所以我在下面创建了类:
ForecastParams.java
import java.util.List;
public class ForecastParams {
public List<_List> list;
}
_List.java
import java.util.List;
public class _List {
public long dt;
public Main main;
public Rain rain;
public Snow snow;
}
主.java
public class Main {
public double temp;
public double feels_like;
public double temp_min;
public double temp_max;
public int pressure;
public int humidity;
}
雨.java
public class Rain {
@SerializedName("3h")
public double rainPrep;
}
雪.java
public class Snow {
@SerializedName("3h")
public double snowPrep;
}
我使用 AsyncTask 从服务器获取 json 然后解析它(在主要活动中):
private class getForecastData extends AsyncTask<String, Void, Reader>{
private Reader json;
@Override
protected Reader doInBackground(String... urls){
try{
json = RestAPIService.getStream(urls[0]);
}catch (Exception e){
e.printStackTrace();
}
return json;
}
@Override
protected void onPostExecute(Reader json){
try{
Gson gson = new Gson();
ForecastParams response = gson.fromJson(json, ForecastParams.class);
List<_List> forecastList = response.list;
double temp = 0;
List<Long> dayTime = new ArrayList<>();
List<Double> temps = new ArrayList<>();
List<Double> rainPrep = new ArrayList<>();
List<Double> snowPrep = new ArrayList<>();
for (_List weather : forecastList){
dayTime.add(weather.dt);
temps.add(weather.main.temp);
rainPrep.add(weather.rain.rainPrep);
snowPrep.add(weather.snow.snowPrep);
}
setDtList(dayTime);
setTempsList(temps);
setRainPrepList(rainPrep);
setSnowPrepList(snowPrep);
}catch (Exception e){
e.printStackTrace();
}
}
}
getStream 就像:
static Reader getStream(String url) throws IOException {
URL obj = new URL(url);
HttpURLConnection connection = (HttpURLConnection)obj.openConnection();
InputStream resBody;
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
resBody = connection.getInputStream();
} else
return null;
connection.disconnect();
Reader resBodyReader = new InputStreamReader(resBody, "UTF-8");
return resBodyReader;
}
启动应用程序时,我收到以下堆栈跟踪:
W/System.err: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
at java.net.SocketInputStream.read(SocketInputStream.java:175)
at java.net.SocketInputStream.read(SocketInputStream.java:144)
at com.android.okhttp.okio.Okio$2.read(Okio.java:136)
W/System.err: at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:50)
at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:393)
at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:371)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:288)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:351)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:180)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1291)
at com.google.gson.stream.JsonReader.skipQuotedValue(JsonReader.java:1119)
at com.google.gson.stream.JsonReader.skipValue(JsonReader.java:1253)
W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:870)
at com.pklos.myweather.MainActivity$getForecastData.onPostExecute(MainActivity.java:243)
at com.pklos.myweather.MainActivity$getForecastData.onPostExecute(MainActivity.java:202)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.access$600(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
当我像这样打开 StrictMode 时(在 onCreate 方法中):
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
我得到这样的堆栈跟踪(套接字关闭):
W/System.err: com.google.gson.JsonSyntaxException: java.net.SocketException: Socket closed
at com.google.gson.Gson.fromJson(Gson.java:947)
at com.google.gson.Gson.fromJson(Gson.java:870)
at com.pklos.myweather.MainActivity$getForecastData.onPostExecute(MainActivity.java:243)
at com.pklos.myweather.MainActivity$getForecastData.onPostExecute(MainActivity.java:202)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.access$600(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:106)
W/System.err: at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:119)
at java.net.SocketInputStream.read(SocketInputStream.java:176)
W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:144)
at com.android.okhttp.okio.Okio$2.read(Okio.java:136)
at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:50)
at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:393)
at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:371)
W/System.err: at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:288)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:351)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:180)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1291)
at com.google.gson.stream.JsonReader.nextQuotedValue(JsonReader.java:1031)
at com.google.gson.stream.JsonReader.nextName(JsonReader.java:788)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:217)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
at com.google.gson.Gson.fromJson(Gson.java:932)
... 12 more
我的问题是为什么套接字关闭了?事实上,我很困惑一个应用程序已经从服务器下载了 json。以同样的方式,我解析另一个 JSON(大约 500 个字符)并且它工作正常。信息量在这里很重要吗?或者处理来自 JSON 的信息的类可能没有以正确的方式编写?有没有其他方法可以处理这个问题?
解决方案
推荐阅读
- javascript - Is there a way to paginate html pages that look like slides in React?
- sql - sql连接多个值列表
- c# - Xamarin Forms XAML: yet another Binding syntax question
- pdf - 更改数据表 pdfmaker 扩展中的字体
- kubernetes - How to use external pod template in Airflow
- excel - 如何从各种工作表中捕获附加行
- emacs - Emacs prefix justifications?
- javascript - Can I provide a json path in CSV file in postman
- node.js - 如何使用从 mongoose 模型调用的 find() 从包含多个模型的集合中获取特定模型?
- c# - 我需要将一个文件分成多个文件,在文件中的特定点分开