预期是BEGIN_OBJECT,但实际上是BEGIN_ARRAY在Retrofit2中。

huangapple go评论59阅读模式
英文:

expected BEGIN_OBJECT but was BEGIN_ARRAY in Retrofit2

问题

我正在尝试使用Retrofit发布这个JSON对象:

{
  "ingredients": [
    {
      "quantity": 1,
      "measureURI": measureUri,
      "foodId": foodId
    }
  ]
}

我成功地使用Python实现了这个:

import requests

APP_ID = "app_id"
API_KEY = "api_key"
BASE = "https://api.edamam.com/api/food-database/v2/nutrients?"

url = f"https://api.edamam.com/api/food-database/v2/nutrients?app_id={APP_ID}&app_key={API_KEY}"
data = {
    "ingredients": [
        {
            "quantity": 1,
            "measureURI": "http://www.edamam.com/ontologies/edamam.owl#Measure_unit",
            "foodId": "food_a1gb9ubb72c7snbuxr3weagwv0dd"
        }
    ]
}

res = requests.post(url, json=data)
print(res.text)

但是我不能用Retrofit做同样的事情。这是我的服务接口:

@POST(Constants.API_PATH_NUTRIENTS + "?app_id=" + Constants.APP_ID + "&app_key=" + Constants.API_KEY)
Call<NutrientsResponseSchema> getFoodNutrients(@Body NutrientsRequestSchema requestSchema);

和请求模型:

public class NutrientsRequestSchema {
    public List<IngredientsRequestSchema> ingredients;

    public NutrientsRequestSchema(List<IngredientsRequestSchema> ingredients) {
        this.ingredients = ingredients;
    }
}
public class IngredientsRequestSchema {
    public float quantity;
    public String foodId;

    @SerializedName("measureURI")
    public String measureUri;

    public IngredientsRequestSchema(float quantity,
                                    String measureUri,
                                    String foodId) {
        this.quantity = quantity;
        this.measureUri = measureUri;
        this.foodId = foodId;
    }
}

当我运行代码并从服务请求时,我收到以下错误:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 298 column 20 path $.ingredients
英文:

I am trying to post this json object with retrofit

{
  &quot;ingredients&quot;: [
    {
      &quot;quantity&quot;: 1,
      &quot;measureURI&quot;: measureUri,
      &quot;foodId&quot;: foodId
    }
  ]
}

I succeeded using python:

import requests

APP_ID = &quot;app_id_&quot;
API_KEY = &quot;api_key&quot;
BASE = &quot;https://api.edamam.com/api/food-database/v2/nutrients?&quot;

url = f&quot;https://api.edamam.com/api/food-database/v2/nutrients?app_id={APP_ID}&amp;app_key={API_KEY}&quot;
data = {
        &quot;ingredients&quot;: [
            {
                &quot;quantity&quot;: 1,
                &quot;measureURI&quot;:  &quot;http://www.edamam.com/ontologies/edamam.owl#Measure_unit&quot;,
                &quot;foodId&quot;:  &quot;food_a1gb9ubb72c7snbuxr3weagwv0dd&quot;
            }
        ]
    }

res = requests.post(url, json=data)
print(res.text) 

But I can not do same with retrofit.
Here is my service interface

@POST(Constants.API_PATH_NUTRIENTS + &quot;?app_id=&quot; + Constants.APP_ID + &quot;&amp;app_key=&quot; + Constants.API_KEY)
Call&lt;NutrientsResponseSchema&gt; getFoodNutrients(@Body NutrientsRequestSchema requestSchema);

And Request schema models

public class NutrientsRequestSchema {
    public List&lt;IngredientsRequestSchema&gt; ingredients;

    public NutrientsRequestSchema(List&lt;IngredientsRequestSchema&gt; ingredients) {
        this.ingredients = ingredients;
    }
}
public class IngredientsRequestSchema {
    public float quantity;
    public String foodId;

    @SerializedName(&quot;measureURI&quot;)
    public String measureUri;

    public IngredientsRequestSchema(float quantity,
                                    String measureUri,
                                    String foodId) {
        this.quantity = quantity;
        this.measureUri = measureUri;
        this.foodId = foodId;
    }
}

When I run code and request from service I get

>
&gt; com.google.gson.JsonSyntaxException:
&gt; java.lang.IllegalStateException: Expected BEGIN_OBJECT but was
&gt; BEGIN_ARRAY at line 298 column 20 path $.ingredients
&gt;

答案1

得分: 1

错误消息很明确,您已经定义了 NutrientsResponseSchema,以使您期望食材是一个对象,但服务器返回的食材明显是一个数组,正如以下所示:

{
  "ingredients": [
    {
      "quantity": 1,
      "measureURI": measureUri,
      "foodId": foodId
    }
  ]
}

ingredients 是一个 Ingredient 数组。但在您的 NutrientsResponseSchema 中,您必须已经定义了如下内容:

@SerializedName("ingredients")
public Ingredient ingredient; //POJO and not a list of POJO

您可以通过将 NutrientsResponseSchema 更改为以下内容轻松解决此问题:

@SerializedName("ingredients")
public List<Ingredient> ingredients; //List of POJO

编辑:为了更好地解释:

您有您的 NutrientsResponseSchema

public class NutrientsResponseSchema {
    public String uri;
    public float calories;
    public float totalWeight;
    public List<String> dietLabels;
    public List<String> healthLabels;
    public List<String> cautions;
 
    public TotalNutrients totalNutrients;
    public Ingredients ingredients;
}

您需要将最后一行更改为:

public class NutrientsResponseSchema {
    public String uri;
    public float calories;
    public float totalWeight;
    public List<String> dietLabels;
    public List<String> healthLabels;
    public List<String> cautions;
 
    public TotalNutrients totalNutrients;
    @SerializedName("ingredients")
    public List<Ingredient> ingredients;
}

Ingredient 可以是:

public class Ingredient{
    public float quantity;
    public String food;
    public String foodId;
    public float weight;
    public float retainedWeight;
    public String measureUri;
    public String status;
}
英文:

The error message is clear, you have defined NutrientsResponseSchema such that, you expected ingredients to be an object but the ingredients from server is definitely an array as suggested by

{
  &quot;ingredients&quot;: [
    {
      &quot;quantity&quot;: 1,
      &quot;measureURI&quot;: measureUri,
      &quot;foodId&quot;: foodId
    }
  ]
}

ingredients is an array of Ingredient. but in your NutrientsResponseSchema, you must have defined

   @SerializedName(&quot;ingredients&quot;)
    public Ingredient ingredient; //POJO and not a list of POJO

You can easily fix this by, changing your NutrientsResponseSchema as

   @SerializedName(&quot;ingredients&quot;)
    public List&lt;Ingredient&gt; ingredients; //List of POJO

EDIT: To explain more:

You have your NutrientsResponseSchema:

public class NutrientsResponseSchema {
    public String uri;
    public float calories;
    public float totalWeight;
    public List&lt;String&gt; dietLabels;
    public List&lt;String&gt; healthLabels;
    public List&lt;String&gt; cautions;
 
    public TotalNutrients totalNutrients;
    public Ingredients ingredients;
}

You need to change your last line to:

public class NutrientsResponseSchema {
    public String uri;
    public float calories;
    public float totalWeight;
    public List&lt;String&gt; dietLabels;
    public List&lt;String&gt; healthLabels;
    public List&lt;String&gt; cautions;
 
    public TotalNutrients totalNutrients;
    @SerializedName(&quot;ingredients&quot;)
    public List&lt;Ingredient&gt; ingredients;
}

and Ingredient can be:

public class Ingredient{
    public float quantity;
    public String food;
    public String foodId;
    public float weight;
    public float retainedWeight;
    public String measureUri;
    public String status;
}

huangapple
  • 本文由 发表于 2020年7月29日 23:14:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63156830.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定