I try to parse JSON like in this snippet using gson:
{
"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"}]
In reality it's much longer, it has approximately 15,000 characters.
All I need are temps, dts, rain or snow precipitation, so I've created classes below:
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;
}
Main.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;
}
Rain.java
public class Rain {
@SerializedName("3h")
public double rainPrep;
}
Snow.java
public class Snow {
@SerializedName("3h")
public double snowPrep;
}
I use AsyncTask to perform getting json from server and then parsing it (in main activity):
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 is like:
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;
}
When launching an app I receive following stack trace:
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)
When I switch the StrictMode on like this (in onCreate method):
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
I get stack trace like this (socket closed):
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
My question is why is the socket closed? I'm confused by fact an app have already downloaded json from server. In the same way I parse another JSON (about 500 characters) and it works properly. Is amount of information crucial here? Or maybe the classes that handles the information from JSON are not written in right way? Is there any other way to handle with this issue?