为什么 JSON 文档没有完全消耗?
Why is JSON document not fully consumed?
我正在尝试从外部来源检索 JSON 数据以进行练习。我已经准备好所有代码,但由于某种原因,我收到一条错误消息,指出文档未完全使用。我已经观看并阅读了多个教程和指南,但似乎仍然无法正确理解。我也在堆栈中搜索了答案,但由于我不知道出了什么问题,所以我真的不知道要寻找什么。
代码全部到位,没有明显的错误。 JSON 数据已经过验证,可以检索原始 JSON 数据,如日志中所示。当数据应该传输到 java 数据 class 时,问题发生在 Gson 转换时。有什么想法可能是错误的吗?
public class JSONimport extends AsyncTask<Void, Void, DeserializedContainer> {
private static final String TAG = "TAG";
//VARIABLES TO HOLD JSON DATA
private OnLoadListener mListener;
//CONSTRUCTOR
public JSONimport(OnLoadListener listener) {
this.mListener = listener;
}
//ASYNK, DO IN BACKGROUND THREAD
@Override
protected DeserializedContainer doInBackground(Void... voids) {
String myJSON = ""; //TEMP VARIABLE TO HOLD JSON DATA
String completeJSONdata = ""; //VARIABLE TO HOLD COMPLETE JSON DATA
try {
URL urlObject = new URL( "https://api.myjson.com/bins/161kkd" );
HttpURLConnection httpURLConnection = (HttpURLConnection) urlObject.openConnection();
InputStream inputStreamObject = httpURLConnection.getInputStream();
BufferedReader bufferedReaderObject = new BufferedReader( new InputStreamReader( inputStreamObject ) );
while (myJSON != null) {
myJSON = bufferedReaderObject.readLine();
completeJSONdata += myJSON;
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.d( TAG, "doInBackground: ERROR RETRIEVING URL" );
} catch (IOException e) {
e.printStackTrace();
Log.d( TAG, "doInBackground: ERROR HTTP CONNECTION" );
}
//DESERIALIZATION, converting JSON to java variables, making the data easy to handle
Gson gsonObject = new GsonBuilder()
.setLenient()
.create();
DeserializedContainer deserializedContainerObject;
deserializedContainerObject = gsonObject.fromJson( completeJSONdata, DeserializedContainer.class );
//Log.d( TAG, "doInBackground: " + deserializedContainerObject.getDeserializedContainerList() );
return deserializedContainerObject;
}
@Override
protected void onPostExecute(final DeserializedContainer result) {
mListener.onSuccess( result );
//FUNKAR ATT HÄMTA JSON DATA. KOLLA LOGCAT
Log.d( TAG, "onPostExecuteLOL: " + result );
}
public static interface OnLoadListener {
void onSuccess(DeserializedContainer container);
}}
错误在deserializedContainerObject = gsonObject.fromJson( completeJSONdata, DeserializedContainer.class );
保存JSON数据的数据对象:
public class DeserializedContainer {
@SerializedName("deserializedContainerList")
public List<DeserializedVariables> deserializedContainerList = new ArrayList<>();
public List<DeserializedVariables> getDeserializedContainerList() {
return deserializedContainerList;
}}
public class DeserializedVariables {
@SerializedName( "movieName" )
private String movieName;
@SerializedName( "movieYear" )
private int movieYear;
@SerializedName( "movieRating" )
private double movieRating;}
来自主线程的相关数据:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
//BACKGROUND THREAD
JSONimport jsonImportObject = new JSONimport( new JSONimport.OnLoadListener() {
@Override
public void onSuccess(DeserializedContainer container) {
container.getDeserializedContainerList();
}
} );
jsonImportObject.execute();
//Log.d( TAG, "onCreateGETTING DATA : " + jsonImportObject.getCompletedData());
DeserializedContainer deserializedContainerObject = new DeserializedContainer();
Log.d( TAG, "onCreate: " + deserializedContainerObject);
JSON:
{"deserializedContainerList":[{"movieName":"filmA","movieYear":2017,"movieRating":4.7},{"movieName": "filmB","movieYear":2018,"movieRating":4.8},{"movieName":"filmC","movieYear":2019,"movieRating": 4.9}]}
抱歉拖了这么久post,希望你有精力熬过去。我真的卡住了。我知道 Retrofit 和类似的库,但我花了很多时间来解决这个问题,所以我还不想放弃它 :P
谢谢!
///////
更新
///////
我根据 Laurent B 的建议更新了代码,它成功了!或者,至少它没有崩溃。我尝试使用以下代码在主线程上打印列表:
for(int i = 0; i < deserializedContainerObject.deserializedContainerList.size(); i++) {
Log.d( TAG, "onCreate: " + deserializedContainerObject.deserializedContainerList.get( i ));
}
但是没有任何显示。检查 deserializedContainerObject.deserializedContainerList.size() 时显示为 0。也就是说,列表中没有添加任何数据……嗯。至少它不会崩溃,多亏了 Laurent B 这么近了一步。
您的完整 JSON 数据不正确,因为您总是将 "null" 放在末尾。
相反,您的 while 子句应该是例如:
while ((myJSON = bufferedReaderObject.readLine()) != null) {
completeJSONdata += myJSON;
}
顺便说一下,不要忘记关闭您的流,例如尝试使用 :
try (InputStream inputStreamObject = httpURLConnection.getInputStream()) {
// ...
}
正在传递值,但是 null 也随之传递,因此请使用 if 语句而不是使用 while
像这样..
if (myJSON != null) {
myJSON = bufferedReaderObject.readLine();
completeJSONdata += myJSON;
}
然后像这样在 Gson 中转换..
Gson gson = new Gson();
deserializedContainerObject = gson.fromJson(completeJSONdata, DeserializedContainer.class);
在 DeserializedVariables
class
中编写 getter 和 setter
public String getMovieName() {
return movieName;
}
public void setMovieName(String movieName) {
this.movieName = movieName;
}
public Integer getMovieYear() {
return movieYear;
}
public void setMovieYear(Integer movieYear) {
this.movieYear = movieYear;
}
public Double getMovieRating() {
return movieRating;
}
public void setMovieRating(Double movieRating) {
this.movieRating = movieRating;
}
现在您可以像这样在 onPostExecute()
中检索它..
@Override
protected void onPostExecute( DeserializedContainer result) {
mListener.onSuccess( result );
for (int i = 0; i <result.deserializedContainerList.size(); i++) {
DeserializedVariables deserializedVariables = result.deserializedContainerList.get(i);
Log.d( TAG, "onPostExecuss: " + deserializedVariables.getMovieName() );
}
}
我正在尝试从外部来源检索 JSON 数据以进行练习。我已经准备好所有代码,但由于某种原因,我收到一条错误消息,指出文档未完全使用。我已经观看并阅读了多个教程和指南,但似乎仍然无法正确理解。我也在堆栈中搜索了答案,但由于我不知道出了什么问题,所以我真的不知道要寻找什么。
代码全部到位,没有明显的错误。 JSON 数据已经过验证,可以检索原始 JSON 数据,如日志中所示。当数据应该传输到 java 数据 class 时,问题发生在 Gson 转换时。有什么想法可能是错误的吗?
public class JSONimport extends AsyncTask<Void, Void, DeserializedContainer> {
private static final String TAG = "TAG";
//VARIABLES TO HOLD JSON DATA
private OnLoadListener mListener;
//CONSTRUCTOR
public JSONimport(OnLoadListener listener) {
this.mListener = listener;
}
//ASYNK, DO IN BACKGROUND THREAD
@Override
protected DeserializedContainer doInBackground(Void... voids) {
String myJSON = ""; //TEMP VARIABLE TO HOLD JSON DATA
String completeJSONdata = ""; //VARIABLE TO HOLD COMPLETE JSON DATA
try {
URL urlObject = new URL( "https://api.myjson.com/bins/161kkd" );
HttpURLConnection httpURLConnection = (HttpURLConnection) urlObject.openConnection();
InputStream inputStreamObject = httpURLConnection.getInputStream();
BufferedReader bufferedReaderObject = new BufferedReader( new InputStreamReader( inputStreamObject ) );
while (myJSON != null) {
myJSON = bufferedReaderObject.readLine();
completeJSONdata += myJSON;
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.d( TAG, "doInBackground: ERROR RETRIEVING URL" );
} catch (IOException e) {
e.printStackTrace();
Log.d( TAG, "doInBackground: ERROR HTTP CONNECTION" );
}
//DESERIALIZATION, converting JSON to java variables, making the data easy to handle
Gson gsonObject = new GsonBuilder()
.setLenient()
.create();
DeserializedContainer deserializedContainerObject;
deserializedContainerObject = gsonObject.fromJson( completeJSONdata, DeserializedContainer.class );
//Log.d( TAG, "doInBackground: " + deserializedContainerObject.getDeserializedContainerList() );
return deserializedContainerObject;
}
@Override
protected void onPostExecute(final DeserializedContainer result) {
mListener.onSuccess( result );
//FUNKAR ATT HÄMTA JSON DATA. KOLLA LOGCAT
Log.d( TAG, "onPostExecuteLOL: " + result );
}
public static interface OnLoadListener {
void onSuccess(DeserializedContainer container);
}}
错误在deserializedContainerObject = gsonObject.fromJson( completeJSONdata, DeserializedContainer.class );
保存JSON数据的数据对象:
public class DeserializedContainer {
@SerializedName("deserializedContainerList")
public List<DeserializedVariables> deserializedContainerList = new ArrayList<>();
public List<DeserializedVariables> getDeserializedContainerList() {
return deserializedContainerList;
}}
public class DeserializedVariables {
@SerializedName( "movieName" )
private String movieName;
@SerializedName( "movieYear" )
private int movieYear;
@SerializedName( "movieRating" )
private double movieRating;}
来自主线程的相关数据:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
//BACKGROUND THREAD
JSONimport jsonImportObject = new JSONimport( new JSONimport.OnLoadListener() {
@Override
public void onSuccess(DeserializedContainer container) {
container.getDeserializedContainerList();
}
} );
jsonImportObject.execute();
//Log.d( TAG, "onCreateGETTING DATA : " + jsonImportObject.getCompletedData());
DeserializedContainer deserializedContainerObject = new DeserializedContainer();
Log.d( TAG, "onCreate: " + deserializedContainerObject);
JSON:
{"deserializedContainerList":[{"movieName":"filmA","movieYear":2017,"movieRating":4.7},{"movieName": "filmB","movieYear":2018,"movieRating":4.8},{"movieName":"filmC","movieYear":2019,"movieRating": 4.9}]}
抱歉拖了这么久post,希望你有精力熬过去。我真的卡住了。我知道 Retrofit 和类似的库,但我花了很多时间来解决这个问题,所以我还不想放弃它 :P
谢谢!
/////// 更新 /////// 我根据 Laurent B 的建议更新了代码,它成功了!或者,至少它没有崩溃。我尝试使用以下代码在主线程上打印列表:
for(int i = 0; i < deserializedContainerObject.deserializedContainerList.size(); i++) {
Log.d( TAG, "onCreate: " + deserializedContainerObject.deserializedContainerList.get( i ));
}
但是没有任何显示。检查 deserializedContainerObject.deserializedContainerList.size() 时显示为 0。也就是说,列表中没有添加任何数据……嗯。至少它不会崩溃,多亏了 Laurent B 这么近了一步。
您的完整 JSON 数据不正确,因为您总是将 "null" 放在末尾。
相反,您的 while 子句应该是例如:
while ((myJSON = bufferedReaderObject.readLine()) != null) {
completeJSONdata += myJSON;
}
顺便说一下,不要忘记关闭您的流,例如尝试使用 :
try (InputStream inputStreamObject = httpURLConnection.getInputStream()) {
// ...
}
正在传递值,但是 null 也随之传递,因此请使用 if 语句而不是使用 while 像这样..
if (myJSON != null) {
myJSON = bufferedReaderObject.readLine();
completeJSONdata += myJSON;
}
然后像这样在 Gson 中转换..
Gson gson = new Gson();
deserializedContainerObject = gson.fromJson(completeJSONdata, DeserializedContainer.class);
在 DeserializedVariables
class
public String getMovieName() {
return movieName;
}
public void setMovieName(String movieName) {
this.movieName = movieName;
}
public Integer getMovieYear() {
return movieYear;
}
public void setMovieYear(Integer movieYear) {
this.movieYear = movieYear;
}
public Double getMovieRating() {
return movieRating;
}
public void setMovieRating(Double movieRating) {
this.movieRating = movieRating;
}
现在您可以像这样在 onPostExecute()
中检索它..
@Override
protected void onPostExecute( DeserializedContainer result) {
mListener.onSuccess( result );
for (int i = 0; i <result.deserializedContainerList.size(); i++) {
DeserializedVariables deserializedVariables = result.deserializedContainerList.get(i);
Log.d( TAG, "onPostExecuss: " + deserializedVariables.getMovieName() );
}
}