【问题标题】:GSON & Volley => Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $GSON & Volley => 预期为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT
【发布时间】:2017-08-26 15:31:12
【问题描述】:

这个错误让我发疯了,我尝试使用不同类型的 Volley 请求,例如 JsonArrayRequestJsonObjectRequest,但没有运气!!

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为 BEGIN_ARRAY 但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT


这是 JSON 响应链接 => http://www.mocky.io/v2/58df83a80f00005922eaf4e1


这是我的模型类

 public class Order {


@SerializedName("status")
@Expose
private String status; //status

@SerializedName("total")
@Expose
private float price; //total


@SerializedName("created_at")
@Expose
private Date time;

@SerializedName("line_items")
@Expose
public List<ItemsNum> lineItems = new ArrayList<ItemsNum>();

@SerializedName("sub_orders")
@Expose
public List<OrdersNum> subOrders = new ArrayList<OrdersNum>();

@SerializedName("shipping_address")
@Expose
public CusAddress cusAdress;

@SerializedName("customer")
@Expose
public Customer customer;


public Order(Customer customer, String status, float price, String cusPicURL, String firstName, String lastName, Date time, List<ItemsNum> lineItems, List<OrdersNum> subOrders, CusAddress cusAdress) {
    this.status = status;
    this.price = price;
    this.customer = customer;
    this.time = time;
    this.lineItems = lineItems;
    this.subOrders = subOrders;
    this.cusAdress = cusAdress;
}


public Date getTime() {
    return time;
}

public void setTime(Date time) {
    this.time = time;
}

public List<ItemsNum> getLineItems() {
    return lineItems;
}

public void setLineItems(List<ItemsNum> lineItems) {
    this.lineItems = lineItems;
}

public List<OrdersNum> getSubOrders() {
    return subOrders;
}

public void setSubOrders(List<OrdersNum> subOrders) {
    this.subOrders = subOrders;
}



public String getStatus() {
    return status;
}

public void setStatus(String status) {
    this.status = status;
}

public float getPrice() {
    return price;
}

public void setPrice(float price) {
    this.price = price;
}

public CusAddress getCusAdress() {
    return cusAdress;
}

public void setCusAdress(CusAddress cusAdress) {
    this.cusAdress = cusAdress;
}



// //////////// Inner-Classes


public class Customer {

    @SerializedName("avatar_url")
    @Expose
    private String cusPicURL; //avatar_url

    @SerializedName("first_name")
    @Expose
    private String firstName; //first_name

    @SerializedName("last_name")
    @Expose
    private String lastName; //last_name

    public String getCusPicURL() {
        return cusPicURL;
    }

    public void setCusPicURL(String cusPicURL) {
        this.cusPicURL = cusPicURL;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

public class CusAddress {

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @SerializedName("address_1")
    @Expose
    public String address;

    @SerializedName("city")
    @Expose
    public String city;

    @SerializedName("state")
    @Expose
    public String state;

    @SerializedName("country")
    @Expose
    public String country;
}

public class ItemsNum {

    @SerializedName("id")
    @Expose
    public Integer id;
}

public class OrdersNum {

    @SerializedName("id")
    @Expose
    public Integer id;
 }
}

我的适配器

  public class OrdersDataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {


public Context context;
private int num;
ArrayList<Order> orders;


public OrdersDataAdapter(ArrayList<Order> orders, Context context) {
    this.orders = orders;

    this.context = context;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.order_card, parent, false);

    return new NewOrderVH(v);

}


@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
    final Order order = this.orders.get(position);
    final NewOrderVH vh1 = (NewOrderVH) holder;
    vh1.setData(orders.get(position));

}

@Override
public int getItemCount() {
    return orders.size();
}


public class NewOrderVH extends RecyclerView.ViewHolder {


    private ImageView cusPic;
    private TextView cusName;
    private TextView CusAdress;
    private TextView vendorsNum;
    private TextView itemsNum;
    private TextView time;


    public NewOrderVH(View itemView) {
        super(itemView);


        orderCard = (CardView) itemView.findViewById(R.id.OrderCard);
        cusPic = (ImageView) itemView.findViewById(R.id.cusPic);
        cusName = (TextView) itemView.findViewById(R.id.cusName);
        CusAdress = (TextView) itemView.findViewById(R.id.CusAdress);
        vendorsNum = (TextView) itemView.findViewById(R.id.vendorsNum);
        itemsNum = (TextView) itemView.findViewById(R.id.itemsNum);
        time = (TextView) itemView.findViewById(R.id.time);


    }

    public void setData(final Order data) {


        cusName.setText(data.customer.getFirstName() + "" + data.customer.getLastName());
        Picasso.with(context).load(data.customer.getCusPicURL()).into(cusPic);
        time.setText(data.getTime().getMinutes());
        vendorsNum.setText(data.getSubOrders().size());
        itemsNum.setText(data.getLineItems().size());
        CusAdress.setText(data.cusAdress.getAddress() + "" + data.cusAdress.getCity() + "" + data.cusAdress.getCountry() + "" + data.cusAdress.getState());

    }


}

}

片段内的请求方法

private void fetchPosts() {


    requestQueue = Volley.newRequestQueue(getActivity());

    StringRequest jRequest = new StringRequest(Request.Method.GET, ENDPOINT, onPostsLoaded, onPostsError);

    requestQueue.add(jRequest);

}


private final Response.Listener<String> onPostsLoaded = new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {

        Gson gson = new Gson();
        Type listType = new TypeToken<List<Order>>() {}.getType();
        modelData = gson.fromJson(response, listType);


        adapter = new OrdersDataAdapter((ArrayList<Order>) modelData, getActivity());
        recyclerView.setAdapter(adapter);
        adapter.setMode(Attributes.Mode.Single);

    }
};

private final Response.ErrorListener onPostsError = new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        Log.e("PostActivity", error.toString());
    }
};

【问题讨论】:

    标签: java android json gson android-volley


    【解决方案1】:

    你的问题是orders 对象。您不会反序列化 orders。你可以解决这个问题

    public class OrderHolder{
        private List<Order> orders;
    
        public List<Order> getOrders(){ return orders; }
    
    } 
    
    OrderHolder holder = new Gson().fromJson(response, OrderHolder.class);
    modelData = holder.getOrders();
    

    JsonElement jelement = new JsonParser().parse(response);
    JsonObject  jobject = jelement.getAsJsonObject();
    String ordersString = jobject.get("orders").getAsString();
    
    Gson gson = new Gson();
    Type listType = new TypeToken<List<Order>>() {}.getType();
    modelData = gson.fromJson(ordersString, listType);
    

    【讨论】:

    • 关于第二种方法,我得到这个错误..!? m15i.imgup.net/xx7c56.JPG
    • 第一种方法给了我这个 ===> java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List .........$2$1OrderHolder.getOrders( )' 在空对象引用上
    • 第一个解决方案需要正确,你确定你得到响应对象吗?并且可以在java.lang.NullPointerException.之前出现反序列化错误
    • 它也不起作用..但我的核心问题出在我身上,因为我从 getgo 实现了错误类型的请求..我使用的是 StringRequest 但我应该使用 JsonObjectRequest 因为响应从一个开始..!无论如何,我会更新正确的解决方案..!非常感谢您的帮助:)
    【解决方案2】:

    预期为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT

    这很容易阅读:这意味着您正在解析类似列表的内容(因此需要 BEGIN_ARRAY [),但给定的 JSON 文档以 BEGIN_OBJECT { 开头,这是由于通过不匹配的预期类型。它发生在 JSON 文档的开头。

    除了mismancanswer之外,还有第三种方式,需要稍微多一点的代码(虽然可以提取到一个方法中),但它不需要包装器或中间JSON树像JsonElement 及其子类(第一种情况可能会消耗更多内存,而第二种情况肯定会消耗更多内存,因为整个中间 JSON 树必须存储在内存中)。

    // JsonReader allows to read JSON token stream
    try ( final JsonReader jsonReader = new JsonReader(new StringReader(JSON)) ) {
        // Just skip the leading `{`
        jsonReader.beginObject();
        // Check if the next property name is what we're expecting
        final String name = jsonReader.nextName();
        if ( !name.equals("orders") ) {
            throw new MalformedJsonException("Unexpected: " + name);
        }
        // If it's fine, then we:
        // * are assuming the JsonReader "pointer" is at the property value now
        // * are asking Gson for the proper type adapter
        @SuppressWarnings("unchecked")
        final TypeAdapter<List<Order>> typeAdapter = (TypeAdapter<List<Order>>) gson.getAdapter(TypeToken.get(orderListType));
        // Just read the orders
        final List<Order> orders = typeAdapter.read(jsonReader);
        System.out.println(orders);
    }
    

    到 POJO 自动转换器/生成器的 JSON 模式并不总是创建最佳映射。例如:

    • ItemsNumOrdersNum 都由相同的 POJO 结构表示,但也可以是 final class Id { @SerializedName("id") final Integer id = null; }
    • 客户avatar_url表示为java.lang.String,但也可以是java.net.URL

    小笔记:

    • Gson 不需要在每次需要反序列化时创建类实例。它们是完全线程安全的,可以实例化一次,然后轻松地重复使用。此外,创建和配置 else Gson 实例可以注入到您的代码中。
    • 使用TypeTokens 生成的Type 实例可以被视为不可变值对象,因此也可以缓存到static final 字段中。

    【讨论】:

    • 嗯,它没有工作.. 但经过一番挖掘,我发现问题与凌空请求类型有关,我使用的是 StringRequest 但我应该使用 JsonObjectRequest 因为响应以一个开头。 .!我会发布正确的解决方案..!非常感谢您的帮助:)
    【解决方案3】:

    这是正确的答案,我使用了错误的请求类型..!

      JsonObjectRequest jsObjRequest = new     
      JsonObjectRequest(Request.Method.GET,ENDPOINT,null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
    
                        Gson gson = new Gson();
                        Type listType = new TypeToken<List<Order>>() {}.getType();
                        try {
    
                            List<Order> o = new ArrayList<>();
                            o = gson.fromJson(response.getJSONArray("orders").toString(), listType);
                            if(o != null && !o.isEmpty()){
    
                                modelData.addAll(o);
                                adapter.notifyDataSetChanged();
                            }
    
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
    
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
    
                    }
                });
    
        requestQueue.add(jsObjRequest);
    
    }
    

    【讨论】:

    • 您能否接受 mismanc 的 answer,因为它确实回答了您在此答案中发现的问题没有提及的具体原始问题?谢谢。
    猜你喜欢
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    相关资源
    最近更新 更多