【问题标题】:cant resolve error BEGIN_ARRAY but was BEGIN_OBJECT无法解决错误 BEGIN_ARRAY 但为 BEGIN_OBJECT
【发布时间】:2018-05-04 08:27:21
【问题描述】:

我在使用改造调用进行解析时遇到问题。这不是重复的问题。我尝试了太多谷歌搜索也尝试了很多解决方案,但在我的情况下它不起作用。所以请不要对这个问题投反对票。

错误

05-04 04:18:48.918 5290-5290/nexus.com.demogrph E/Error: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

这是我的回复数据

{
  "market_cap_by_available_supply": [
    [
      1367174841000,
      1500517590
    ],
    [
      1367261101000,
      1575032004
    ]
   ],
   "price_btc": [
    [
      1367174841000,
      1
    ],
    [
      1367261101000,
      1
    ]
   ],
  "price_usd": [
    [
      1367174841000,
      135.3
    ],
    [
      1367261101000,
      141.96
    ]
   ],
   "volume_usd": [
    [
      1367174841000,
      0
    ],
    [
      1367261101000,
      0
    ]
   ]
}

这里我尝试使用 Retrofit 调用 API。

ApiClient.java

public class ApiClient {

    public static final String URL      = "https://graphs2.coinmarketcap.com/";
    public static Retrofit RETROFIT     = null;
//    https://api.coinmarketcap.com/v2/ticker/

    public static Retrofit getClient(){
        if(RETROFIT==null){
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(new LoggingInterceptor())
                    .build();
            RETROFIT = new Retrofit.Builder()
                    .baseUrl(URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return RETROFIT;
    }
}

ApiService.interface

public interface ApiService {
    @GET("currencies/{id}")
    Call<List<PriceDatum>> getPriceData(@Path("id") String id);
}

PriceDatum.java

class PriceDatum implements Serializable {
    @SerializedName("market_cap_by_available_supply")
    @Expose
    private List<Integer> marketCapByAvailableSupply = null;
    @SerializedName("price_btc")
    @Expose
    private List<Integer> priceBtc = null;
    @SerializedName("price_usd")
    @Expose
    private List<Integer> priceUsd = null;
    @SerializedName("volume_usd")
    @Expose
    private List<Integer> volumeUsd = null;

    public List<Integer> getMarketCapByAvailableSupply() {
        return marketCapByAvailableSupply;
    }

    public void setMarketCapByAvailableSupply(List<Integer> marketCapByAvailableSupply) {
        this.marketCapByAvailableSupply = marketCapByAvailableSupply;
    }

    public List<Integer> getPriceBtc() {
        return priceBtc;
    }

    public void setPriceBtc(List<Integer> priceBtc) {
        this.priceBtc = priceBtc;
    }

    public List<Integer> getPriceUsd() {
        return priceUsd;
    }

    public void setPriceUsd(List<Integer> priceUsd) {
        this.priceUsd = priceUsd;
    }

    public List<Integer> getVolumeUsd() {
        return volumeUsd;
    }

    public void setVolumeUsd(List<Integer> volumeUsd) {
        this.volumeUsd = volumeUsd;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {
    List<PriceDatum> datalist;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ApiService apiService =
                ApiClient.getClient().create(ApiService.class);

        Call<List<PriceDatum>> call = apiService.getPriceData("bitcoin");
        call.enqueue(new Callback<List<PriceDatum>>() {
            @Override
            public void onResponse(Call<List<PriceDatum>> call, Response<List<PriceDatum>> response) {
                datalist = response.body();
                Log.d("data", "Number of movies received: " + datalist.size());
            }

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

【问题讨论】:

  • 发布堆栈跟踪
  • 你的 JSON 不是 JSONArray,而是 JSONObject,它有一个 JSONArray 字段。这就是错误所说的。
  • @AnuraagBaishya 检查更改问题。
  • @VladyslavMatviienko 是的,我知道,但是如何使用改造来解析这种类型的响应我尝试了 man 解决方案,但没有成功解决错误。

标签: android json parsing retrofit2


【解决方案1】:

试试这个我测试它现在工作.. 像下面的代码一样制作 pojo 类..

public class Response {
@SerializedName("market_cap_by_available_supply")
@Expose
public List<List<Integer>> market_cap_by_available_supply = null;
@SerializedName("price_btc")
@Expose
public List<List<Integer>> price_btc = null;
@SerializedName("price_usd")
@Expose
public List<List<Integer>> price_usd = null;
@SerializedName("volume_usd")
@Expose
public List<List<Integer>> volume_usd = null;

public List<List<Integer>> getMarket_cap_by_available_supply() {
    return market_cap_by_available_supply;
}

public void setMarket_cap_by_available_supply(List<List<Integer>> market_cap_by_available_supply) {
    this.market_cap_by_available_supply = market_cap_by_available_supply;
}

public List<List<Integer>> getPrice_btc() {
    return price_btc;
}

public void setPrice_btc(List<List<Integer>> price_btc) {
    this.price_btc = price_btc;
}

public List<List<Integer>> getPrice_usd() {
    return price_usd;
}

public void setPrice_usd(List<List<Integer>> price_usd) {
    this.price_usd = price_usd;
}

public List<List<Integer>> getVolume_usd() {
    return volume_usd;
}

public void setVolume_usd(List<List<Integer>> volume_usd) {
    this.volume_usd = volume_usd;
}

@Override
public String toString() {
    return
            "Response{" +
                    "price_usd = '" + price_usd + '\'' +
                    ",market_cap_by_available_supply = '" + market_cap_by_available_supply + '\'' +
                    ",price_btc = '" + price_btc + '\'' +
                    ",volume_usd = '" + volume_usd + '\'' +
                    "}";
}

}

然后像下面这样改造对象类..

public class ApiClient {
private final static String BASE_URL = "https://graphs2.coinmarketcap.com/";

public static ApiClient apiClient;
private Retrofit retrofit = null;
private Retrofit retrofit2 = null;

public static ApiClient getInstance() {
    if (apiClient == null) {
        apiClient = new ApiClient();
    }
    return apiClient;
}

//private static Retrofit storeRetrofit = null;

public Retrofit getClient() {
    return getClient(null);
}


private Retrofit getClient(final Context context) {

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient.Builder client = new OkHttpClient.Builder();
    client.readTimeout(60, TimeUnit.SECONDS);
    client.writeTimeout(60, TimeUnit.SECONDS);
    client.connectTimeout(60, TimeUnit.SECONDS);
    client.addInterceptor(interceptor);
    client.addInterceptor(new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            return chain.proceed(request);
        }
    });

    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();


    return retrofit;
}

}

然后制作如下的api接口..

public interface ApiInterface {
@GET("currencies/bitcoin/")
Call<Response> getHero();

}

然后最终在主要活动中调用api,如下方法..

    private void getApiCall() {
    ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
    Call<Response> responseCall = apiInterface.getHero();
    responseCall.enqueue(new Callback<Response>() {
        @Override
        public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
            if (response.isSuccessful() && response != null && response.body() != null) {
                Log.d("data", response.body().toString());

            }
        }

        @Override
        public void onFailure(Call<Response> call, Throwable t) {

        }
    });

}

【讨论】:

  • 我尝试了您的解决方案,但又遇到了同样的错误,例如 java.lang.IllegalStateException: Expected an int but was BEGIN_ARRAY at line 1 column 38 path $.market_cap_by_available_supply[0]
【解决方案2】:

查看响应,您的 PriceDatum.java 类中有一些错误。进行以下更改 -

@SerializedName("market_cap_by_available_supply")
@Expose
public List<List<Integer>> market_cap_by_available_supply = null;
@SerializedName("price_btc")
@Expose
public List<List<Integer>> price_btc = null;
@SerializedName("price_usd")
@Expose
public List<List<Integer>> price_usd = null;
@SerializedName("volume_usd")
@Expose
public List<List<Integer>> volume_usd = null;

【讨论】:

  • 非常感谢您对我的帮助。解决我的问题
猜你喜欢
  • 1970-01-01
  • 2015-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 2017-05-16
  • 2016-12-27
  • 2013-08-10
相关资源
最近更新 更多