【问题标题】:GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?GSON 抛出“预期为 BEGIN_OBJECT 但为 BEGIN_ARRAY”?
【发布时间】:2012-03-24 19:36:54
【问题描述】:

我正在尝试解析像这样的 JSON 字符串

[
   {
      "updated_at":"2012-03-02 21:06:01",
      "fetched_at":"2012-03-02 21:28:37.728840",
      "description":null,
      "language":null,
      "title":"JOHN",
      "url":"http://rus.JOHN.JOHN/rss.php",
      "icon_url":null,
      "logo_url":null,
      "id":"4f4791da203d0c2d76000035",
      "modified":"2012-03-02 23:28:58.840076"
   },
   {
      "updated_at":"2012-03-02 14:07:44",
      "fetched_at":"2012-03-02 21:28:37.033108",
      "description":null,
      "language":null,
      "title":"PETER",
      "url":"http://PETER.PETER.lv/rss.php",
      "icon_url":null,
      "logo_url":null,
      "id":"4f476f61203d0c2d89000253",
      "modified":"2012-03-02 23:28:57.928001"
   }
]

到对象列表中。

List<ChannelSearchEnum> lcs = (List<ChannelSearchEnum>) new Gson().fromJson( jstring , ChannelSearchEnum.class);

这是我正在使用的对象类。

import com.google.gson.annotations.SerializedName;

public class ChannelSearchEnum {



@SerializedName("updated_at")
private String updated_at;

@SerializedName("fetched_at")
private String fetched_at;

@SerializedName("description")
private String description;

@SerializedName("language")
private String language;

@SerializedName("title")
private String title;

@SerializedName("url")
private String url;

@SerializedName("icon_url")
private String icon_url;

@SerializedName("logo_url")
private String logo_url;

@SerializedName("id")
private String id;

@SerializedName("modified")
private String modified;

public final String get_Updated_at() {
    return this.updated_at;
}

public final String get_Fetched_at() {
    return this.fetched_at;
}

public final String get_Description() {
    return this.description;
}

public final String get_Language() {
    return this.language;
}

public final String get_Title() {
    return this.title;
}

public final String get_Url() {
    return this.url;
}

public final String get_Icon_url() {
    return this.icon_url;
}

public final String get_Logo_url() {
    return this.logo_url;
}

public final String get_Id() {
    return this.id;
}

public final String get_Modified() {
    return this.modified;
}

        }

但它让我感到震惊

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2

任何想法我应该如何解决它?

【问题讨论】:

  • @Soni - 这是不正确的。如果你去 jsonlint.org 并复制/粘贴他的 JSON,你会发现它是有效的。
  • @Soni - 不,删除了“[”和“]”,但还是一样。猜测可能更多,因为我拥有的字符串包含多个对象,而不仅仅是一个。
  • 你在代码中提到的jstring 是什么样的?
  • 我观察到一个想法,当响应返回数组然后尝试接受 List 时,它解决了我的问题。
  • 另外,请检查您的 API 接口是否具有正确的返回类型。当您期望 List 但将 Object 定义为返回类型时,就会发生这种情况。

标签: java android gson


【解决方案1】:

问题是你告诉Gson你有一个你的类型的对象。你没有。您有一个类型的对象数组。你不能只是尝试像那样投射结果并期望它神奇地工作;)

Gson 的用户指南解释了如何处理这个问题:

https://github.com/google/gson/blob/master/UserGuide.md

这将起作用:

ChannelSearchEnum[] enums = gson.fromJson(yourJson, ChannelSearchEnum[].class);

但这样更好:

Type collectionType = new TypeToken<Collection<ChannelSearchEnum>>(){}.getType();
Collection<ChannelSearchEnum> enums = gson.fromJson(yourJson, collectionType);

【讨论】:

  • 可能确实如此。作为对象数组,该类型在运行时保留,因此 gson 知道要查找的内容。好主意。
  • +1 表示TypoToken&lt;Collection&lt;Something&gt;&gt;——当您可以拥有 Collection(子类)和/或 Iterables 时,不要使用数组。
  • 你认为解析选定的 obj/array 是正确的方法吗?帮助stackoverflow.com/questions/18140830/…
  • 如果我们想用字符串制作它怎么办;例如,我可以写类似 String[] t = gson.fromJson(myJson,String[].class)
  • 感觉这个答案还没完!!
【解决方案2】:

问题是您要的是ChannelSearchEnum 类型的对象,但您实际拥有的是List&lt;ChannelSearchEnum&gt; 类型的对象。

您可以通过以下方式实现:

Type collectionType = new TypeToken<List<ChannelSearchEnum>>(){}.getType();
List<ChannelSearchEnum> lcs = (List<ChannelSearchEnum>) new Gson()
               .fromJson( jstring , collectionType);

【讨论】:

  • 那是什么Type?要导入什么?
  • @S.Matthew_English 最有可能java.lang.reflect.Type
【解决方案3】:

在我的例子中是 JSON 字符串:

[{"category":"College Affordability",
  "uid":"150151",
  "body":"Ended more than $60 billion in wasteful subsidies for big banks and used the savings to put the cost of college within reach for more families.",
  "url":"http:\/\/www.whitehouse.gov\/economy\/middle-class\/helping middle-class-families-pay-for-college",
  "url_title":"ending subsidies for student loan lenders",
  "type":"Progress",
  "path":"node\/150385"}]

我在 recycleview 中打印“category”和“url_title”

基准类

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Datum {
@SerializedName("category")
@Expose
private String category;
@SerializedName("uid")
@Expose
private String uid;
@SerializedName("url_title")
@Expose
private String urlTitle;

/**
 * @return The category
 */
public String getCategory() {
    return category;
}

/**
 * @param category The category
 */
public void setCategory(String category) {
    this.category = category;
}

/**
 * @return The uid
 */
public String getUid() {
    return uid;
}

/**
 * @param uid The uid
 */
public void setUid(String uid) {
    this.uid = uid;
}

/**
 * @return The urlTitle
 */
public String getUrlTitle() {
    return urlTitle;
}

/**
 * @param urlTitle The url_title
 */
public void setUrlTitle(String urlTitle) {
    this.urlTitle = urlTitle;
}

}

请求接口

import java.util.List;

import retrofit2.Call;
import retrofit2.http.GET;

/**
 * Created by Shweta.Chauhan on 13/07/16.
 */

public interface RequestInterface {

   @GET("facts/json/progress/all")
   Call<List<Datum>> getJSON();
}

数据适配器

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Shweta.Chauhan on 13/07/16.
 */

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.MyViewHolder>{

private Context context;
private List<Datum> dataList;

public DataAdapter(Context context, List<Datum> dataList) {
    this.context = context;
    this.dataList = dataList;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.data,parent,false);
    return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    holder.categoryTV.setText(dataList.get(position).getCategory());
    holder.urltitleTV.setText(dataList.get(position).getUrlTitle());

}

@Override
public int getItemCount() {
    return dataList.size();
}

public class MyViewHolder extends RecyclerView.ViewHolder{

    public TextView categoryTV, urltitleTV;

    public MyViewHolder(View itemView) {
        super(itemView);
        categoryTV = (TextView) itemView.findViewById(R.id.txt_category);
        urltitleTV = (TextView)     itemView.findViewById(R.id.txt_urltitle);
    }
}
}

最后是 MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {

private RecyclerView recyclerView;
private DataAdapter dataAdapter;
private List<Datum> dataArrayList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initViews();
}

private void initViews(){
    recyclerView=(RecyclerView) findViewById(R.id.recycler_view);
    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
    loadJSON();
}

private void loadJSON(){
    dataArrayList = new ArrayList<>();
    Retrofit retrofit=new Retrofit.Builder().baseUrl("https://www.whitehouse.gov/").addConverterFactory(GsonConverterFactory.create()).build();
    RequestInterface requestInterface=retrofit.create(RequestInterface.class);
    Call<List<Datum>> call= requestInterface.getJSON();
    call.enqueue(new Callback<List<Datum>>() {
        @Override
        public void onResponse(Call<List<Datum>> call, Response<List<Datum>> response) {
            dataArrayList = response.body();
            dataAdapter=new DataAdapter(getApplicationContext(),dataArrayList);
            recyclerView.setAdapter(dataAdapter);
        }

        @Override
        public void onFailure(Call<List<Datum>> call, Throwable t) {
            Log.e("Error",t.getMessage());
        }
    });
}
}

【讨论】:

  • 此类问题的最佳答案
  • 这完美地回答了这个问题,特别是对于改装用户。对于任何寻求清晰的人,您最需要的部分是 Call> getJSON();
  • 你能用协程完成同样的任务吗??
【解决方案4】:

可以选择

让你的回复看起来像

myCustom_JSONResponse

{"master":[
   {
      "updated_at":"2012-03-02 21:06:01",
      "fetched_at":"2012-03-02 21:28:37.728840",
      "description":null,
      "language":null,
      "title":"JOHN",
      "url":"http://rus.JOHN.JOHN/rss.php",
      "icon_url":null,
      "logo_url":null,
      "id":"4f4791da203d0c2d76000035",
      "modified":"2012-03-02 23:28:58.840076"
   },
   {
      "updated_at":"2012-03-02 14:07:44",
      "fetched_at":"2012-03-02 21:28:37.033108",
      "description":null,
      "language":null,
      "title":"PETER",
      "url":"http://PETER.PETER.lv/rss.php",
      "icon_url":null,
      "logo_url":null,
      "id":"4f476f61203d0c2d89000253",
      "modified":"2012-03-02 23:28:57.928001"
   }
]
}

而不是

server_JSONResponse

[
   {
      "updated_at":"2012-03-02 21:06:01",
      "fetched_at":"2012-03-02 21:28:37.728840",
      "description":null,
      "language":null,
      "title":"JOHN",
      "url":"http://rus.JOHN.JOHN/rss.php",
      "icon_url":null,
      "logo_url":null,
      "id":"4f4791da203d0c2d76000035",
      "modified":"2012-03-02 23:28:58.840076"
   },
   {
      "updated_at":"2012-03-02 14:07:44",
      "fetched_at":"2012-03-02 21:28:37.033108",
      "description":null,
      "language":null,
      "title":"PETER",
      "url":"http://PETER.PETER.lv/rss.php",
      "icon_url":null,
      "logo_url":null,
      "id":"4f476f61203d0c2d89000253",
      "modified":"2012-03-02 23:28:57.928001"
   }
]

代码

  String server_JSONResponse =.... // the string in which you are getting your JSON Response after hitting URL
String myCustom_JSONResponse="";// in which we will keep our response after adding object element to it
     MyClass apiResponse = new MyClass();

     myCustom_JSONResponse="{\"master\":"+server_JSONResponse+"}";



    apiResponse = gson.fromJson(myCustom_JSONResponse, MyClass .class);

在此之后它将是任何其他GSON Parsing

【讨论】:

  • 如果我无法更改我的 json 格式怎么办?我正在使用 volley 的 gson 请求来设置我的模型类。怎么做?谢谢
  • @KaveeshKanwal 尝试此线程中提供的其他解决方案,除此之外我不知道
【解决方案5】:

根据GSON User guide,你不能。

集合限制

可以序列化任意对象的集合,但不能反序列化。因为用户无法指明结果对象的类型

【讨论】:

  • 他没有任意对象的集合,他有一个 一个特定类型的对象的集合,Gson 会很乐意处理
  • 实际上,我就像你一样用 TypeToken 写了一个答案,但由于泛型类型没有在运行时嵌入,我看不出它是如何工作的。 (虽然我还没有测试过)。
【解决方案6】:

这看起来像一个Json数组列表。因此最好使用ArrayList来处理数据。在你的 api 端点添加这样的数组列表

 @GET("places/")
Call<ArrayList<Place>> getNearbyPlaces(@Query("latitude") String latitude, @Query("longitude") String longitude);

【讨论】:

    【解决方案7】:

    您需要让 Gson 知道您的回复的其他类型,如下所示

    import com.google.common.reflect.TypeToken;
    import java.lang.reflect.Type;
    
    
    Type collectionType = new TypeToken<List<UserSite>>(){}.getType();
    List<UserSite> userSites  = gson.fromJson( response.getBody() , collectionType);
    

    【讨论】:

    • 补充:Gson gson = new GsonBuilder().create();
    【解决方案8】:

    科特林:

    var list=ArrayList<Your class name>()
    val listresult: Array<YOUR CLASS NAME> = Gson().fromJson(
                    YOUR JSON RESPONSE IN STRING,
                    Array<Your class name>:: class.java)
    
    list.addAll(listresult)
    

    【讨论】:

    • 我没有对任何内容投赞成票或反对票,只是进行了编辑。
    【解决方案9】:

    我不确定这是否是使用 GSON 的最佳方式,但对我有用。你可以在MainActivity上使用这样的一些:

     public void readJson() {
        dataArrayList = new ArrayList<>();
        String json = "[\n" + IOHelper.getData(this) + "\n]\n";
        Log.d(TAG, json);
        try{
            JSONArray channelSearchEnums = new JSONArray(json);
    
            for(int i=0; i< channelSearchEnums.length(); i++)
            {
                JSONObject enum = channelSearchEnums.getJSONObject(i);
                ChannelSearchEnum channel = new ChannelSearchEnum(
                       enum.getString("updated_at"), enum.getString("fetched_at"),
                       enum.getString("description"), enum.getString("language"),
                       enum.getString("title"), enum.getString("url"),
                       enum.getString("icon_url"), enum.getString("logo_url"),
                       enum.getString("id"), enum.getString("modified"))         
    
                       dataArrayList.add(channel);
            }
    
             //The code and place you want to show your data            
    
        }catch (Exception e)
        {
            Log.d(TAG, e.getLocalizedMessage());
        }
    }
    

    你只有字符串,但如果你有 double 或 int,你也可以输入 getDoublegetInt

    接下来是IOHelper类的方法(这里路径保存在内部Storage上):

     public static String getData(Context context) {
        try {
            File f = new File(context.getFilesDir().getPath() + "/" + fileName);
            //check whether file exists
            FileInputStream is = new FileInputStream(f);
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            return new String(buffer);
        } catch (IOException e) {
            Log.e("TAG", "Error in Reading: " + e.getLocalizedMessage());
            return null;
        }
    }
    

    如果你想了解更多关于这方面的信息,你可以看this video,我在这里得到readJson()的代码;和this thread 我得到getData() 的代码。

    【讨论】:

      【解决方案10】:
      public ChannelSearchEnum[] getChannelSearchEnum(Response response) {
              return response.as(ChannelSearchEnum[].class, ObjectMapperType.GSON);
      }
      

      上面将解决并传递响应将返回该类的映射对象数组

      【讨论】:

        【解决方案11】:

        解决方案

        1. 我正在使用 volley 库。我使用 GSON 自动解析截击响应
        
            [
                    {
                        "name": "Naruto: Shippuuden",
                        "description": "It has been two and a half years since Naruto Uzumaki left Konohagakure, the Hidden Leaf Village, for intense training following events which fueled his desire to be stronger. Now Akatsuki, the mysterious organization of elite rogue ninja, is closing in on their grand plan which may threaten the safety of the entire shinobi world.",
                        "Rating": "8.16",
                        "episode": 500,
                        "categorie":"Animation | Drama | Adventure",
                        "studio":"Studio Pierrot",
                        "img": "https://myanimelist.cdn-dena.com/images/anime/5/17407.jpg"
                    },
                    {
                        "name": "One Piece",
                        "description": "Gol D. Roger was known as the 'Pirate King',the strongest and most infamous being to have sailed the Grand Line. The capture and death of Roger by the World Government brought a change throughout the world. His last words before his death revealed the existence of the greatest treasure in the world, One Piece. It was this revelation that brought about the Grand Age of Pirates, men who dreamed of finding One Piece—which promises an unlimited amount of riches and fame—and quite possibly the pinnacle of glory and the title of the Pirate King.",
                        "Rating": "8.54",
                        "episode": 700,
                         "categorie":"Animation | Drama | Adventure",
                        "studio":"Toei Animation",
                        "img": "https://myanimelist.cdn-dena.com/images/anime/6/73245.jpg"
                    }
                ]
        
        

        2.这是我的模特

        
            public class DataResponse implements Serializable {
            
                @SerializedName("studio")
                private String studio;
            
                @SerializedName("img")
                private String img;
            
                @SerializedName("categorie")
                private String categorie;
            
                @SerializedName("Rating")
                private String rating;
            
                @SerializedName("name")
                private String name;
            
                @SerializedName("description")
                private String description;
            
                @SerializedName("episode")
                private int episode;
            
                public void setStudio(String studio){
                    this.studio = studio;
                }
            
                public String getStudio(){
                    return studio;
                }
            
                public void setImg(String img){
                    this.img = img;
                }
            
                public String getImg(){
                    return img;
                }
            
                public void setCategorie(String categorie){
                    this.categorie = categorie;
                }
            
                public String getCategorie(){
                    return categorie;
                }
            
                public void setRating(String rating){
                    this.rating = rating;
                }
            
                public String getRating(){
                    return rating;
                }
            
                public void setName(String name){
                    this.name = name;
                }
            
                public String getName(){
                    return name;
                }
            
                public void setDescription(String description){
                    this.description = description;
                }
            
                public String getDescription(){
                    return description;
                }
            
                public void setEpisode(int episode){
                    this.episode = episode;
                }
            
                public int getEpisode(){
                    return episode;
                }
            
                @Override
                public String toString(){
                    return 
                        "Response{" + 
                        "studio = '" + studio + '\'' + 
                        ",img = '" + img + '\'' + 
                        ",categorie = '" + categorie + '\'' + 
                        ",rating = '" + rating + '\'' + 
                        ",name = '" + name + '\'' + 
                        ",description = '" + description + '\'' + 
                        ",episode = '" + episode + '\'' + 
                        "}";
                    }
            }
        
        
        1. 我的api方法
        define globle
        
        private List<DataResponse> dataResponses = new ArrayList<>();
        
        
        
            private void volleyAutomation(String url) {
                    JSONArray array = new JSONArray();
                    JsonArrayRequest request_json = new JsonArrayRequest(Request.Method.GET, url, array,
                            new Response.Listener<JSONArray>() {
                                @Override
                                public void onResponse(JSONArray response) {
            
                                    GsonBuilder gsonBuilder = new GsonBuilder();
                                    Gson gson = gsonBuilder.create();
                                   dataResponses = Arrays.asList(gson.fromJson(response.toString(), DataResponse[].class));
            
                                    rvList(dataResponses);
                                    Log.d("respknce___", String.valueOf(dataResponses.size()));
                                }
                            }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError volleyError) {
            
                        }
                    });
                    RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
                    requestQueue.add(request_json);
                }
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多