【问题标题】:Andorid Studio java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $Android Studio java.lang.IllegalStateException:应为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT
【发布时间】:2021-08-02 19:40:57
【问题描述】:

我知道这不是关于此错误的第一个问题。我到处寻找答案,但找不到解决办法。当我运行代码时,我得到了这个异常;

java.lang.IllegalStateException:应为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $

处为 BEGIN_OBJECT

主要活动

public class MainActivity extends AppCompatActivity {
    ArrayList<Doviz> dovizs;

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

        Retrofit retrofit= new Retrofit.Builder()
                .baseUrl("https://finans.truncgil.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        DovizApi dovizApi = retrofit.create(DovizApi.class);

        Call<List<Doviz>> call = dovizApi.getDoviz();

      

        call.enqueue(new Callback<List<Doviz>>() {

            @Override
            public void onResponse(Call<List<Doviz>> call, Response<List<Doviz>> response) {
                System.out.println("deneme");
                List<Doviz> responseList= response.body();
                dovizs = new ArrayList<>(responseList);
                System.out.println(dovizs.get(0).USD);

            }

            @Override
            public void onFailure(Call<List<Doviz>> call, Throwable t) {
                System.out.println(t.fillInStackTrace());
            }
        });
    }
}

Java 类

public class Doviz {

    @SerializedName("Buying")
    public String USD;

}

界面

public interface DovizApi {
    @GET("today.json")
    Call<List<Doviz>> getDoviz();
}

我使用的列表 https://finans.truncgil.com/v3/today.json

我已经处理这个问题好几天了。我希望我们能解决它

【问题讨论】:

  • 此错误行 1 列 2 路径 $ 是因为您的 API 重新检查您的 API。

标签: java android retrofit retrofit2


【解决方案1】:

发生了什么?

  • API 响应的根是 JSONObject 而不是 JSONArray。
  • API URL 中缺少 v3。

解决方案

更新界面

public interface DovizApi {
    @GET("v3/today.json")
    Call<HashMap<String, Object>> getDoviz();
}

更新响应模型(Doviz)

public class Doviz {
   @SerializedName("Buying")
   public String buying;

   // Similarly you can add other keys here
}

更新改造调用

Call<HashMap<String, Object>> call = dovizApi.getDoviz();
call.enqueue(new Callback<HashMap<String, Object>>() {

        @Override
        public void onResponse(Call<HashMap<String, Object>> call, Response<HashMap<String, Object>> response) {
            HashMap<String, Object> responseModel = response.body();

            // Iterate all the currencies
            for (Map.Entry<String, Object> entry : responseModel.entrySet())
                if(entry.getValue() instanceof LinkedTreeMap) { // Since the first element is of type String i.e. "Update_Date"
                    Doviz doviz = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap<String, Object>) entry.getValue())), Doviz.class);
                    System.out.println("Currency = " + entry.getKey() +
                                     ", Buying = " + doviz.buying);
                }
        }

        @Override
        public void onFailure(Call<HashMap<String, Object>> call, Throwable t) {
            System.out.println(t.fillInStackTrace());
        }
    });

【讨论】:

  • 我试过了,但我得到了这个例外。 " java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'java.util.Set java.util.HashMap.entrySet()' 我该怎么办?
  • @DoğukanÇiftçi 我在验证后更新了答案。它现在应该可以工作了。请在解决方案部分更新上述代码库。
  • 你是最棒的,非常感谢它现在正在工作。但我想问你一个私人问题。为什么我们使用HashMap?我们可以用什么来代替 HashMap?这段代码 ''Doviz doviz = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap) entry.getValue())), Doviz.class);'' 是什么意思。你是怎么学会这些的?是的,问题已解决,但我不明白它是如何发生的。我仍然无法自己编写此代码,我该如何学习?再次感谢您有一个健康的日子。
  • @DoğukanÇiftçi 很高兴听到问题已解决。使用 HashMap 的原因是因为您的响应是具有货币的自定义键(不是固定键)。您可以通过深入研究 Gson 库来了解更多信息。
  • 感谢您的帮助,但我再次需要您的帮助,因为我不完全了解我们的工作。我必须在 recyclerview 中使用这个变量(货币名称和购买)。我该如何使用它?我脑子里的一切都那么混乱。 ArrayLists、Lists、HashMaps ...
【解决方案2】:

检查点

  1. 类型

Json 如下所示

{
   "Update_Date":"2021-05-12 16:00:01",
   "USD":{
      "Buying":"8,3681",
      "Type":"Currency",
      "Selling":"8,3735",
      "Change":"%1,13"
   },
   ...
}

这不是&lt;List&gt;USD 是json 中的关键之一

所以Call&lt;List&lt;Doviz&gt;&gt; 应该更改为Call&lt;Doviz&gt;

  1. DTO(多维兹)

您可能希望Buying 的值为USD。 你是 DTO(Doviz) 应该拥有像这样的另一个 DTO 的属性

  class Doviz {
        @SerializedName("USD")
        CurrencyInfo usd;
       
        // else like this
        @SerializedName("EUR")
        CurrencyInfo eur;

        //...
  }

  class CurrencyInfo {
        //if Path(/v3) included
        @SerializedName("Buying")
        String buying;

        //if Path (/v3) not included 
        @SerializedName("Alış")
        String _buying;

       // else.. 
 }

interface DovizApi{
        @GET("/v3/today.json")
        fun getEnDoviz(): Call<Doviz>
}
Call<Doviz> call = dovizApi.getDoviz();
call.enqueue(new Callback<Doviz>(){
            @Override
            public void onResponse(Call<Doviz> call,Response<Doviz>response){
                Doviz doviz = response.body();
                CurrencyInfo info = doviz.getUsd();
                System.out.println(info.getBuying());
            }
..
}

效果很好。

【讨论】:

  • 当我这样做时,我得到了另一个错误。 "列表 responseList= response.body();"这部分不起作用。它说''java.lang.ClassCastException:com.example.parsingjson.Doviz 不能转换为 java.util.List''
  • List&lt;Doviz&gt; 应更改为 Doviz。这不是列表
猜你喜欢
  • 2022-11-25
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 2021-04-14
  • 1970-01-01
  • 2019-11-27
  • 2020-04-10
相关资源
最近更新 更多