【问题标题】:Getting ArrayList from JSON response using Retrofit 2使用 Retrofit 2 从 JSON 响应中获取 ArrayList
【发布时间】:2016-11-18 12:13:01
【问题描述】:

我知道这已被多次询问,但查看已有的答案,我无法解决我的问题,所以任何帮助将不胜感激。

我正在尝试使用 Retrofit 2 的自定义反序列化器将我的 JSON 响应解析为数组列表。但它给了我错误

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为 BEGIN_ARRAY,但在路径 $ 处为 BEGIN_OBJECT

这是我要解析的 json 响应

[
  {
    "category": "Accessories"
  },
  {
    "category": "Apparel"
  },
  {
    "category": "Audio CD"
  },
  {
    "keyword": "Accessories & Supplies"
  },
  {
    "keyword": "Audio & Video Accessories"
  },
  {
    "keyword": "Combination Deodorants & Antiperspirants"
  },
  {
    "_id": "57442700d0fcd01100d45cd8",
    "prodName": "2015 High-end Case Cover zzzzzzz Animals dobermans nature puppies Samsung Galaxy S7 phone Case 3236386XK945021729S7 Jordan Dowdy's Shop"
  },
  {
    "_id": "575a95fbb9167e100054f5ab",
    "prodName": "30 Piece Brand New & Sealed Hard Candy' Cosmetics Makeup Excellent Assorted Mixed Lot"
  },
  {
    "_id": "57442700d0fcd01100d45cd5",
    "prodName": "8274363XK945021729I5S New Premium zzzzzzz Animals dobermans nature puppies Skin Case Cover Excellent Fitted For iPhone SE/iPhone 5/5s Gary R. Morones's Shop"
  },
  {
    "_id": "575a95fbb9167e100054f5b0",
    "prodName": "ACE Fashion Women Professional 15 Color Makeup Cosmetic Contour Concealer Palette Make Up+Sponge+Concealer Brush"
  }
]

这是自定义反序列化器

public static class HomeSearchDeserializer implements JsonDeserializer<ArrayList<HomeSearchItems>> {
    @Override
    public ArrayList<HomeSearchItems> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws Js

        Log.v("JSON RESPONSE " + String.valueOf(countlog++), String.valueOf(json));
        Gson gson = new Gson();
        Type listType = new TypeToken<ArrayList<HomeSearchItems>>() {
        }.getType();
        ArrayList<HomeSearchItems> HomeSearchItemsList = new Gson().fromJson(json, listType);
        final JsonArray jsonArray = json.getAsJsonArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            HomeSearchItems homeSearchItems = new HomeSearchItems();
            JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
            if (!jsonObject.get("prodName").isJsonNull()) {
                homeSearchItems.set_id(jsonObject.get("_id").getAsString());
                homeSearchItems.setTitle(jsonObject.get("prodName").getAsString());
                homeSearchItems.setType(HomeSearchItems.ItemType.product);
            } else if (!jsonObject.get("category").isJsonNull()) {
                homeSearchItems.setTitle(jsonObject.get("category").getAsString());
                homeSearchItems.setType(HomeSearchItems.ItemType.category);
            } else {
                homeSearchItems.setTitle(jsonObject.get("keyword").getAsString());
                homeSearchItems.setType(HomeSearchItems.ItemType.keyword);
            }
            HomeSearchItemsList.add(homeSearchItems);
        }
        return HomeSearchItemsList;
    }
}
public static GsonConverterFactory HomeSearchGsonConverter() {
    GsonBuilder gsonBuilder = new GsonBuilder();
    // Adding custom deserializers
    gsonBuilder.registerTypeAdapter(HomeSearchItems.class, new Search.HomeSearchDeserializer());
    Gson myGson = gsonBuilder.create();
    return GsonConverterFactory.create(myGson);
}

这是 GET 改造电话

public interface SearchCalls {
    @GET("/products/search")
    Call<ArrayList<HomeSearchItems>> HomeSearch(@Header("Authorization") String Token, @Query("queryString") String query);
}

这是我进行网络调用的函数

public void callSearch(String query) {
                //Toast.makeText(getApplicationContext(),query,Toast.LENGTH_SHORT);
                Log.v("query", query);


                HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
                httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

                OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
                httpClient.addInterceptor(new Interceptor() {
                    @Override
                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request original = chain.request();

                        Request request = original.newBuilder()
                                .header("Content-Type", "application/json")
                                .method(original.method(), original.body())
                                .build();

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

                httpClient.addInterceptor(httpLoggingInterceptor);


                OkHttpClient client = httpClient.build();
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(baseURL)
                        .addConverterFactory(HomeSearchGsonConverter())
                        .client(client)
                        .build();

                Search.SearchCalls service = retrofit.create(Search.SearchCalls.class);
                Call<ArrayList<HomeSearchItems>> HomeSearch = service.HomeSearch("Bearer " +appSettings.getToken(),query);


                HomeSearch.enqueue(new Callback<ArrayList<HomeSearchItems>>() {
                    @Override
                    public void onResponse(Call<ArrayList<HomeSearchItems>> call, Response<ArrayList<HomeSearchItems>> response) {
                        Log.v("onResponse,Code", String.valueOf(response.code()));
                        if (response.isSuccessful()) {
                            HomeSearchItemsList = response.body();
                            Log.v("onResponse", "isSuccessful TRUE");
                        } else {
                            Log.v("onResponse", "isSuccessful FALSE");
                        }
                    }

                    @Override
                    public void onFailure(Call<ArrayList<HomeSearchItems>> call, Throwable t) {
                        Log.v("onFailure", t.toString());
                    }
                });

            }

HomeSearchItemsListHomeSearchItems

类型的 ArrayList

这是 HomeSearchItems 类

public class HomeSearchItems {

    public enum ItemType {
        product, keyword, category
    }

    private String title;
    private ItemType type;
    private String _id;


    public HomeSearchItems() {

    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public ItemType getType() {
        return type;
    }

    public void setType(ItemType type) {
        this.type = type;
    }

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }
}

编辑 1 堆栈跟踪

V/query: a
D/OkHttp: --> GET https://houston.tm.smartfission.com:3030/products/search?queryString=a http/1.1
D/OkHttp: Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjE2NCwiZXhwIjoxNDczNjY0Mjg5fQ.ROBvKkoC0Gud4AFghYtUku_OXBRYWjzHeR5Dkhd1mOc
D/OkHttp: --> END GET
D/OkHttp: <-- 200 OK https://houston.tm.smartfission.com:3030/products/search?queryString=a (2010ms)
D/OkHttp: X-Powered-By: Express
D/OkHttp: Access-Control-Allow-Origin: *
D/OkHttp: Access-Control-Allow-Methods: GET,PUT,POST,DELETE,PATCH,OPTIONS
D/OkHttp: Access-Control-Allow-Headers: Content-Type, Authorization, Accept-Encoding, Accept-Language
D/OkHttp: Content-Type: application/json; charset=utf-8
D/OkHttp: Content-Length: 891
D/OkHttp: ETag: W/"37b-Qfnf0ExmUd0oo2dJpmXG2g"
D/OkHttp: Vary: Accept-Encoding
D/OkHttp: Date: Fri, 15 Jul 2016 11:02:31 GMT
D/OkHttp: Connection: keep-alive
D/OkHttp: [{"category":"Accessories"},{"category":"Apparel"},{"category":"Audio CD"},{"keyword":"Accessories & Supplies"},{"keyword":"Audio & Video Accessories"},{"keyword":"Combination Deodorants & Antiperspirants"},{"_id":"57442700d0fcd01100d45cd8","prodName":"2015 High-end Case Cover zzzzzzz Animals dobermans nature puppies Samsung Galaxy S7 phone Case 3236386XK945021729S7 Jordan Dowdy's Shop"},{"_id":"575a95fbb9167e100054f5ab","prodName":"30 Piece Brand New & Sealed Hard Candy' Cosmetics Makeup Excellent Assorted Mixed Lot"},{"_id":"57442700d0fcd01100d45cd5","prodName":"8274363XK945021729I5S New Premium zzzzzzz Animals dobermans nature puppies Skin Case Cover Excellent Fitted For iPhone SE/iPhone 5/5s Gary R. Morones's Shop"},{"_id":"575a95fbb9167e100054f5b0","prodName":"ACE Fashion Women Professional 15 Color Makeup Cosmetic Contour Concealer Palette Make Up+Sponge+Concealer Brush"}]
D/OkHttp: <-- END HTTP (891-byte body)
V/onFailure: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at path $

编辑 2

该行被抛出异常:

ArrayList<HomeSearchItems> HomeSearchItemsList = new Gson().fromJson(json, listType);

文档说,

抛出: JsonSyntaxException - 如果 json 不是 typeOfT 类型对象的有效表示

【问题讨论】:

  • 发布完整的堆栈跟踪
  • 什么是堆栈跟踪?
  • 您在 log cat 中看到的错误,有关更多详细信息,请参阅:en.wikipedia.org/wiki/Stack_trace
  • @AshishRanjan 请参阅编辑 1
  • 您的 JSON 格式不符合预期。您期待一个对象数组列表,但您的 JSON 只有单个值

标签: java android arraylist retrofit2


【解决方案1】:

您的 JSON 格式不符合您的要求。

以下 JSON 结构可能适合您 -

[
    { 
     "category": "Accessories", 
     "keyword": "Accessories & Supplies", 
     "_id": "57442700d0fcd01100d45cd8",
     "prodName": "2015 High-end Case Cover zzzzzzz Animals dobermans nature puppies Samsung Galaxy S7 phone Case 3236386XK945021729S7 Jordan Dowdy's Shop" 
    },
    {
     "category": "Apparel", 
     "keyword": "Audio & Video Accessories", 
     "_id": "575a95fbb9167e100054f5ab"
     "prodName": "30 Piece Brand New & Sealed Hard Candy' Cosmetics Makeup Excellent Assorted Mixed Lot"
    }
]

这可能适用于您的数据模型,但您的反序列化器中有一些杂乱无章的东西,您可能需要再次查看。

请参阅this 链接以了解有关如何定义 JSON 数据的更多信息。这肯定会有所帮助。

【讨论】:

  • 我无法控制 json 响应,也无法修改它,所以我现在应该如何进行,才能将响应解析为 java?
  • @AsadTariq 强烈感觉回复格式不对。我也不知道如何进一步进行,但我认真地认为您应该与负责此奇怪响应的服务团队交谈。最好现在改正。
  • 后端团队负责服务器及其设置。他们开发了整个 iOS 应用程序,该应用程序在调用该服务器时运行良好,所以我怀疑他们会改变结构。我负责将应用程序移植到安卓,所以我必须坚持这个回应。请以任何方式指导我,如何解析此响应。返回的数组可以包含 3 种可能的元素类型 1. 类别 2. 关键字 3. 产品 我必须将它们全部添加到列表中并将列表显示给用户。
  • @AsadTariq 你能把你的下面一行替换掉吗 ArrayList HomeSearchItemsList = new Gson().fromJson(json, listType); with ArrayList HomeSearchItemsList = new ArrayList ();
  • 我在反序列化函数的开头添加了这一行Log.v("JSON RESPONSE " + String.valueOf(countlog++), String.valueOf(json));,相应的输出是V/JSON RESPONSE 0: {"category":"Accessories"}我应该得到一个json数组但我得到一个json对象
猜你喜欢
  • 2016-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
相关资源
最近更新 更多