GSON выбрасывает «Ожидаемый BEGIN_OBJECT, но был BEGIN_ARRAY»?

Я пытаюсь разобрать строку 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 

Любые идеи, как мне это исправить?

Проблема в том, что вы говорите 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); 

Проблема в том, что вы запрашиваете объект типа channelSearchEnum но то, что вы на самом деле имеете, является объектом типа List<channelSearchEnum> .

Вы можете добиться этого с помощью:

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

В моем случае строка 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"}] 

И я печатаю «category» и «url_title» в recycleview

Datum.class

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

RequestInterface

 import java.util.List; import retrofit2.Call; import retrofit2.http.GET; 

/ ** * Создано Shweta.Chauhan 13/07/16. * /

 public interface RequestInterface { @GET("facts/json/progress/all") Call<List<Datum>> getJSON(); 

}

DataAdapter

 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; 

/ ** * Создано Shweta.Chauhan 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()); } }); } } 

Альтернативой может быть

Чтобы ваш ответ выглядел

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

В соответствии с руководством пользователя GSON вы не можете.

Ограничения коллекций

Может сериализовать сбор произвольных объектов, но не может десериализоваться из него. Поскольку пользователю не указывается тип результирующего объекта