GSON “BEGIN_OBJECT bekleniyordu ama BEGIN_ARRAY mıydı?”


295

Bunun gibi bir JSON dizesini ayrıştırmaya çalışıyorum

[
   {
      "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"
   }
]

bir nesne listesine.

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

İşte kullandığım bir nesne sınıfı.

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

        }

Ama beni atar

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

Herhangi bir fikir nasıl düzeltmek gerekir?


12
@Soni - bu yanlış. Jsonlint.org adresine gidip JSON kopyalayıp yapıştırırsanız, geçerli olduğunu göreceksiniz.
Brian Roach

@Soni - hayır, "[" ve ​​"]" ifadelerini kaldırdı, ancak yine de aynı. çünkü daha fazla olabilir çünkü ben dizi dize sadece bir değil, birden fazla nesne içerir.
Roger Travis

Ne yapar jstringkodunuzda ima böyle bir görünüm?
IgorGanapolsky

Ben bir düşünmek gözlemlemek, dizi yanıt dönüş sonra liste almaya çalışın, bu benim sorunum çözmek.
iamkdblue

Yanıtlar:


331

Sorun şu ki Gson, türünüzün bir nesnesine sahip olduğunuzu söylüyorsunuz . Yapmazsın. Türünüzde bir dizi nesneniz var. Sadece sonucu bu şekilde yayınlayamazsınız ve sihirli bir şekilde çalışmasını bekleyemezsiniz;)

Bununla Gsonnasıl başa çıkılacağını açıklayan Kullanım kılavuzu :

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

Bu çalışacak:

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

Ama bu daha iyi:

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

muhtemelen. bir nesne dizisi olarak, tür çalışma zamanında tutulur, böylece gson ne arayacağını bilir. İyi bir fikir.
njzk2

3
TypoToken<Collection<Something>>Koleksiyon için +1 (alt sınıflar) ve / veya Yinelenebilir olduğunda dizileri kullanmayın.
Philipp Reichart

Seçili obj / array'i ayrıştırmanın doğru yöntem olduğunu düşünüyor musunuz? help stackoverflow.com/questions/18140830/…
LOG_TAG

1
Ya dize ile yapmak istersek; Örneğin bir dize [] t = gson.fromJson (. MyJson, String [] sınıfı) gibi bir yazma
Şahin Yanlık

4
Bu cevabı hissetmek bitmemiş !!
EngineSense

45

Sorun, bir nesne türünü sormanızdır, ChannelSearchEnumancak aslında sahip olduğunuz türden bir nesnedir List<ChannelSearchEnum>.

Bunu aşağıdakilerle yapabilirsiniz:

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

1
bu nasıl bir şey Type? ne ithal etmeli?
smatthewenglish

4
S.Matthew_English büyük olasılıklajava.lang.reflect.Type
Guillaume Polet

36

Benim durumumda JSON dizesi:

[{"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"}]

ve geri dönüşüm görünümünde "kategori" ve "url_title" yazdım

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;

/**
 * Created by Shweta.Chauhan on 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;

/**
 * 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);
    }
}
}

ve son olarak 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());
        }
    });
}
}

5
bu tür bir sorun için en iyi cevap
Nicky Manali

4
Bu, özellikle retrofit kullanıcıları için soruyu mükemmel bir şekilde cevaplıyor. Netlik arayan herkes için en çok ihtiyaç duyduğunuz kısım <List <Datum>> getJSON () öğesini arayın;
Carlos Anyona

13

Alternatif olabilir

cevabınızı benzetmek için

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

onun yerine

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

KOD

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

Bundan sonra sadece başka olacak GSON Parsing


json biçimimi değiştiremezsem ne olur? Model sınıfımı ayarlamak için volley'nin gson isteğini kullanıyorum. Nasıl yapılır? Teşekkürler
Kaveesh Kanwal

@KaveeshKanwal bu konuda verilen diğer çözümleri deneyin, bunun dışında hiçbir fikrim yok
DeltaCap019

8

GSON Kullanım kılavuzuna göre yapamazsınız.

Koleksiyon Sınırlamaları

Rasgele nesnelerin toplanmasını serileştirebilir ancak ondan serileştiremez. Kullanıcının ortaya çıkan nesnenin türünü belirtmesinin bir yolu olmadığından


7
Keyfi nesnelerden oluşan bir koleksiyonu yok , mutlu bir şekilde başa çıkacak belirli bir nesne türünden bir koleksiyonu Gsonvar
Brian Roach

aslında, tıpkı yaptığınız gibi TypeToken ile bir cevap yazarak başladım, ancak genel tür çalışma zamanında gömülü olmadığından, bunun nasıl çalışabileceğini görmedim. (Ben test etmedim rağmen).
njzk2

3

Bu bir Json dizi listesine benziyor.Bu ArrayListnedenle verileri işlemek için kullanmak en iyisidir . API uç noktanıza böyle bir dizi listesi ekleyin

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

1

Gson'a yanıtınızın ek türünü aşağıdaki gibi bildirmeniz gerekir

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

1

Bunun GSON'u kullanmanın en iyi yolu olup olmadığından emin değilim, ama benim için çalışıyor. Şunun gibi bir şey kullanabilirsiniz 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());
    }
}

Yalnızca dizeleriniz var, ancak iki katına ya da int'e sahip olsaydınız, getDoubleya getIntda koyabilirsiniz .

IOHelperSınıf yöntemi sonraki (Burada, yol dahili depolama birimine kaydedilir):

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

Bu konuda daha fazla bilgi istiyorsanız , kodunu aldığım bu videoyu görebilirsiniz readJson(); ve bu iş parçasının kodunu aldım getData().


0

Kotlin:

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)

Hiçbir şeyi onaylamamış veya küçümsemedim, sadece düzenledim.
Shredator
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.