为什么 JSON 文档没有被完全消费?

2022-01-19 00:00:00 json network-programming android java gson

我正在尝试从外部来源检索 JSON 数据以进行练习.我已经准备好所有代码,但由于某种原因,我收到一条错误消息,指出文档未完全使用.我已经观看并阅读了多个教程和指南,但似乎仍然无法正确理解.我也搜索了堆栈以寻找答案,但由于我不知道出了什么问题,我真的不知道要寻找什么.

I'm trying to retrieve JSON data from an external source for practice. I have gotten all the code in place but for some reason I get an error saying that the document is not fully consumed. I have watched and read multiple tutorials and guides, but still can't seem to get it right. I have also searched stack for answers, but since I don't know what's wrong, I don't really know what to look for.

所有代码都到位,没有明显的错误.JSON 数据已经过验证,可以作为原始 JSON 数据进行检索,如日志中所示.当数据应传输到 java 数据类时,在 Gson 转换时会出现问题.有什么想法可能是错的吗?

All the code is in place and there is no obvious fault in it. The JSON data has been validated and it works to retrieve as raw JSON data, as seen in a log. The problem occur at the Gson conversion when the data should be transferred to a java data class. Any ideas what could be wrong?

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);

The error is at deserializedContainerObject = gsonObject.fromJson( completeJSONdata, DeserializedContainer.class );

保存 JSON 数据的数据对象:

The data objects to hold the JSON data:

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;}

来自主线程的相关数据:

Relevant data from the main thread:

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}]}

{"deserializedContainerList":[{"movieName":"filmA","movieYear":2017,"movieRating":4.7},{"movieName":"filmB","movieYear":2018,"movieRating":4.8},{"movieName":"filmC","movieYear":2019,"movieRating":4.9}]}

抱歉这么长的帖子,希望你有精力看完.我真的被困住了.我知道 Retrofit 和类似的库,但是我花了很多时间来做到这一点,以至于我还不想放弃它:P

Sorry for such a long post, hope you have the energy to go through it. I'm really stuck. I know of Retrofit and similar libraries, but I have spent so many hours on getting this right that I don't want to abandon it just yet :P

谢谢!

///////更新///////我根据 Laurent B 的建议更新了代码,并且成功了!或者,至少它没有崩溃.我尝试使用以下代码在主线程上打印列表:

/////// UPDATE /////// I updated the code according to Laurent B's suggestion, and it worked! Or, at least it didn't crash. I tried printing the list on the main thread with the following code:

for(int i = 0; i < deserializedContainerObject.deserializedContainerList.size(); i++) {
        Log.d( TAG, "onCreate: " + deserializedContainerObject.deserializedContainerList.get( i ));

    }

但什么也没显示.在检查 deserializedContainerObject.deserializedContainerList.size() 时,它显示为 0.也就是说,没有数据被添加到列表中......嗯.至少它不会崩溃,这要归功于 Laurent B 更近了一步.

But nothing showed. When checking deserializedContainerObject.deserializedContainerList.size() it showed 0. That is, no data has been added to the list... Hmmm. At least it doesn't crash, thanks to Laurent B so one step closer.

推荐答案

值被传递,但是 null 也被传递,所以使用 if 语句而不是使用 while像这样..

The value is being pass, but however null is also getting passed with it so use an if statement rather than using while like this..

if (myJSON != null) {
                myJSON = bufferedReaderObject.readLine();
                completeJSONdata += myJSON;
            }

然后像这样在 Gson 中转换..

then convert in Gson like this..

    Gson gson = new Gson();
    deserializedContainerObject = gson.fromJson(completeJSONdata, DeserializedContainer.class);

DeserializedVariables类中编写getter和setter

write the getters and setters in 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() 中检索它..

And now you can retrieve it in your onPostExecute() like this..

@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() );
        }

    }

相关文章