自定义TypeAdapter for Retrofit 2.0

时间:2017-07-07 04:05:45

标签: android retrofit2

我正在使用API​​,它提供了我需要的更多信息。 我使用Retrofit和GSON获取数据并创建具有所需值的POJO列表。 我创建了一个自定义的TypeAdapter,在其中,我得到了响应并返回了一个对象列表。使用本地JSON对象时,它可以与自定义TypeAdapter一起使用,但是使用Retrofit我就会出错。

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

任何想法为什么会这样?我做错了什么?

编辑:

我更改了GsonBuilder,将正确的类型传递给Retrofit Builder,如下所示:

Type collectionType = new TypeToken<List<Article>>(){}.getType();
    gsonBuilder.registerTypeAdapter(collectionType,new ArticleTypeAdapter());

JSON

{
"status": "OK",
"copyright": "Copyright (c) 2017 The New York Times Company.  All Rights Reserved.",
"num_results": 5,
"results": [
    {
        "url": "https://www.nytimes.com/2017/06/29/automobiles/autoreviews/video-review-a-family-friendly-ferrari-for-the-family-of-means.html",
        "adx_keywords": "Ferrari SpA;Ferrari GTC4Lusso;Automobiles",
        "column": "Driven",
        "section": "Automobiles",
        "byline": "By TOM VOELK",
        "type": "Article",
        "title": "Video Review: A Family-Friendly Ferrari, for the Family of Means",
        "abstract": "The all-wheel-drive V12 GTC4Lusso seats four comfortably. With its svelte silhouette, it may look like a station wagon. It is anything but.",
        "published_date": "2017-06-29",
        "source": "The New York Times",
        "id": 100000005178442,
        "asset_id": 100000005178442,
        "views": 1,
        "des_facet": [
            "AUTOMOBILES"
        ],
        "org_facet": [
            "FERRARI SPA"
        ],
        "per_facet": "",
        "geo_facet": "",
        "media": [
            {
                "type": "image",
                "subtype": "photo",
                "caption": "Ferrari GTC4Lusso",
                "copyright": "Martin Campbell",
                "approved_for_syndication": 1,
                "media-metadata": [
                    {
                        "url": "https://static01.nyt.com/images/2017/06/26/automobiles/autoreviews/27driven1/27driven1-thumbStandard.jpg",
                        "format": "Standard Thumbnail",
                        "height": 75,
                        "width": 75
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/06/26/automobiles/autoreviews/27driven1/27driven1-mediumThreeByTwo210.jpg",
                        "format": "mediumThreeByTwo210",
                        "height": 140,
                        "width": 210
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/06/26/automobiles/autoreviews/27driven1/27driven1-mediumThreeByTwo440.jpg",
                        "format": "mediumThreeByTwo440",
                        "height": 293,
                        "width": 440
                    }
                ]
            }
        ]
    },
    {
        "url": "https://www.nytimes.com/2017/07/06/automobiles/wheels/luxury-cars-dealers-sales.html",
        "adx_keywords": "Automobiles;Luxury Goods and Services;Customer Relations;United States;Lexus Division of Toyota Motor Corp;Cadillac Division of General Motors Corp;Alfa Romeo Automobiles;Lincoln Motor Co",
        "column": "Wheels",
        "section": "Automobiles",
        "byline": "By ERIC A. TAUB",
        "type": "Article",
        "title": "How to Soothe Luxury-Car Buyers: Add Perks and Subtract Haggling",
        "abstract": "Several automakers aim to change the shopping experience with fixed prices, after-sale care and even ways to avoid the dealership altogether.",
        "published_date": "2017-07-06",
        "source": "The New York Times",
        "id": 100000005135624,
        "asset_id": 100000005135624,
        "views": 2,
        "des_facet": [
            "AUTOMOBILES",
            "LUXURY GOODS AND SERVICES",
            "CUSTOMER RELATIONS"
        ],
        "org_facet": [
            "LEXUS DIVISION OF TOYOTA MOTOR CORP",
            "CADILLAC DIVISION OF GENERAL MOTORS CORP",
            "ALFA ROMEO AUTOMOBILES",
            "LINCOLN MOTOR CO"
        ],
        "per_facet": "",
        "geo_facet": [
            "UNITED STATES"
        ],
        "media": [
            {
                "type": "image",
                "subtype": "photo",
                "caption": "Lexus has introduced a fixed-price program, called Lexus Plus, in which the buyer deals with only one person from beginning to end.",
                "copyright": "Alex Wroblewski for The New York Times",
                "approved_for_syndication": 1,
                "media-metadata": [
                    {
                        "url": "https://static01.nyt.com/images/2017/07/06/business/07WHEELS1/07WHEELS1-thumbStandard.jpg",
                        "format": "Standard Thumbnail",
                        "height": 75,
                        "width": 75
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/07/06/business/07WHEELS1/07WHEELS1-mediumThreeByTwo210.jpg",
                        "format": "mediumThreeByTwo210",
                        "height": 140,
                        "width": 210
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/07/06/business/07WHEELS1/07WHEELS1-mediumThreeByTwo440.jpg",
                        "format": "mediumThreeByTwo440",
                        "height": 293,
                        "width": 440
                    }
                ]
            }
        ]
    },
    {
        "url": "https://www.nytimes.com/2017/06/29/automobiles/wheels/why-fog-lamps-are-starting-to-disappear.html",
        "adx_keywords": "Automobile Safety Features and Defects;AAA Foundation for Traffic Safety;Mercedes-Benz;Consumer Reports;Insurance Institute for Highway Safety",
        "column": "Wheels",
        "section": "Automobiles",
        "byline": "By JAMES G. COBB",
        "type": "Article",
        "title": "Why Fog Lamps Are Starting to Disappear",
        "abstract": "Several luxury automakers have moved away from fog lights, saying that new high-tech headlights render them obsolete.",
        "published_date": "2017-06-29",
        "source": "The New York Times",
        "id": 100000005172500,
        "asset_id": 100000005172500,
        "views": 3,
        "des_facet": [
            "AUTOMOBILE SAFETY FEATURES AND DEFECTS"
        ],
        "org_facet": [
            "AAA FOUNDATION FOR TRAFFIC SAFETY",
            "MERCEDES-BENZ",
            "CONSUMER REPORTS",
            "INSURANCE INSTITUTE FOR HIGHWAY SAFETY"
        ],
        "per_facet": "",
        "geo_facet": "",
        "media": [
            {
                "type": "image",
                "subtype": "photo",
                "caption": "General Motors’ headquarters and other buildings in the Detroit skyline, obscured by early morning fog. Some automakers have quietly omitted front fog lights from many new models, saying that high-tech headlights make them unnecessary.",
                "copyright": "Kevin Miyazaki for The New York Times",
                "approved_for_syndication": 1,
                "media-metadata": [
                    {
                        "url": "https://static01.nyt.com/images/2017/06/29/business/30WHEELS1/30WHEELS1-thumbStandard.jpg",
                        "format": "Standard Thumbnail",
                        "height": 75,
                        "width": 75
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/06/29/business/30WHEELS1/30WHEELS1-mediumThreeByTwo210.jpg",
                        "format": "mediumThreeByTwo210",
                        "height": 140,
                        "width": 210
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/06/29/business/30WHEELS1/30WHEELS1-mediumThreeByTwo440.jpg",
                        "format": "mediumThreeByTwo440",
                        "height": 293,
                        "width": 440
                    }
                ]
            }
        ]
    },
    {
        "url": "https://www.nytimes.com/2017/07/06/automobiles/autoreviews/video-review-volvo-v90-cross-country-rolls-into-suv-territory.html",
        "adx_keywords": "Automobiles;Volvo Car Corp;2017 Volvo V90 Cross Country",
        "column": "Driven",
        "section": "Automobiles",
        "byline": "By TOM VOELK",
        "type": "Article",
        "title": "Video Review: Volvo V90 Cross Country Rolls Into S.U.V. Territory",
        "abstract": "Americans are buying S.U.V.s and crossovers in record numbers, but it’s worth keeping an open mind about Volvo’s station wagon.",
        "published_date": "2017-07-06",
        "source": "The New York Times",
        "id": 100000005194798,
        "asset_id": 100000005194798,
        "views": 4,
        "des_facet": [
            "AUTOMOBILES"
        ],
        "org_facet": [
            "VOLVO CAR CORP"
        ],
        "per_facet": "",
        "geo_facet": "",
        "media": ""
    },
    {
        "url": "https://www.nytimes.com/2017/06/08/automobiles/saab-autos-cars.html",
        "adx_keywords": "Automobiles;Saab Automobile AB;Bankruptcies;Portland (Ore)",
        "column": "Wheels",
        "section": "Automobiles",
        "byline": "By NICK KURCZEWSKI",
        "type": "Article",
        "title": "In Portland, a Rare Outpost for Die-Hard Saab Fans",
        "abstract": "The Swedish automaker filed for bankruptcy in 2011, leaving a vanishingly small number of dealerships for fans of the company.",
        "published_date": "2017-06-08",
        "source": "The New York Times",
        "id": 100000005095241,
        "asset_id": 100000005095241,
        "views": 5,
        "des_facet": [
            "AUTOMOBILES",
            "BANKRUPTCIES"
        ],
        "org_facet": [
            "SAAB AUTOMOBILE AB"
        ],
        "per_facet": "",
        "geo_facet": [
            "PORTLAND (ORE)"
        ],
        "media": [
            {
                "type": "image",
                "subtype": "photo",
                "caption": "Saab filed for bankruptcy in 2011, but Garry Small Saab in Portland, Ore., has continued to service and sell the brand’s cars.",
                "copyright": "Amanda Lucier for The New York Times",
                "approved_for_syndication": 1,
                "media-metadata": [
                    {
                        "url": "https://static01.nyt.com/images/2017/06/08/business/09WHEELS1/09WHEELS1-thumbStandard.jpg",
                        "format": "Standard Thumbnail",
                        "height": 75,
                        "width": 75
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/06/08/business/09WHEELS1/09WHEELS1-mediumThreeByTwo210.jpg",
                        "format": "mediumThreeByTwo210",
                        "height": 140,
                        "width": 210
                    },
                    {
                        "url": "https://static01.nyt.com/images/2017/06/08/business/09WHEELS1/09WHEELS1-mediumThreeByTwo440.jpg",
                        "format": "mediumThreeByTwo440",
                        "height": 293,
                        "width": 440
                    }
                ]
            }
        ]
    }
]

}

输入适配器的读取方法

public List<Article> read(JsonReader in) throws IOException {

    final List<Article> article_list = new ArrayList<>();
    in.beginObject();
    while(in.hasNext()){
        switch (in.nextName()){
            case "results":
                in.beginArray();
                while(in.hasNext()){
                    final Article article = new Article();
                    in.beginObject();
                    while (in.hasNext()){
                        switch (in.nextName()){

                            case "id":
                                article.setId(Long.valueOf(in.nextString()));
                                break;
                            case "title":
                                article.setTitle(in.nextString());
                                break;
                            case "url":
                                article.setUrl(in.nextString());
                                break;
                            case "adx_keywords":
                                article.setAdxKeywords(in.nextString());
                                break;
                            case "section":
                                article.setSection(in.nextString());
                                break;
                            case "byline":
                                article.setByline(in.nextString());
                                break;
                            case "abstract":
                                article.set_abstract(in.nextString());
                                break;
                            case "published_date":
                                article.setPublishedDate(in.nextString());
                                break;
                            case "media":
                                if(!in.peek().equals(JsonToken.BEGIN_ARRAY)){
                                    in.skipValue();
                                    break;
                                }
                                in.beginArray();
                                final ArrayList<Media> media_list = new ArrayList<>();
                                while(in.hasNext()){
                                    in.beginObject();
                                    while(in.hasNext()){
                                        switch (in.nextName()){
                                            case "media-metadata":
                                                in.beginArray();
                                                while(in.hasNext()){
                                                    in.beginObject();
                                                    final Media media = new Media();
                                                    while(in.hasNext()){
                                                        switch (in.nextName()){
                                                            case "url":
                                                                media.setUrl(in.nextString());
                                                                break;
                                                            case "format":
                                                                media.setFormat(in.nextString());
                                                                break;
                                                            default:
                                                                in.skipValue();
                                                                break;
                                                        }
                                                    }
                                                    in.endObject();
                                                    media_list.add(media);
                                                }
                                                in.endArray();
                                                break;
                                            default:
                                                in.skipValue();
                                                break;
                                        }
                                    }
                                    in.endObject();
                                }
                                in.endArray();
                                for(Media m : media_list){
                                    if(m.getFormat().equals("mediumThreeByTwo440")){
                                        article.setMedia(m);
                                        break;
                                    }
                                }
                                break;

                            default:
                                in.skipValue();
                                break;
                        }/**/
                    }
                    in.endObject();
                    article_list.add(article);
                }
                in.endArray();
                break;
            default:
                in.skipValue();
                break;

        }

    }
    in.endObject();

    Timber.d(article_list.toString());
    return article_list;
}

文章和媒体类(无方法)

public class Article {
private Long id;
private String url;
private String adxKeywords;
private String section;
private String byline;
private String title;
private String _abstract;
private String publishedDate;
private Media media;
}

public class Media {
private String url;
private String format;
}

改造生成器

final GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(Article.class,new ArticleTypeAdapter());
    final Gson gson = gsonBuilder.create();
    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

1 个答案:

答案 0 :(得分:-1)

你需要做这样的事情: -

public class Response{
    public String status;
    public String copyright;
    public int num_results;
    public Article[] results;
}

您必须传递一个响应类,其响应结构与您从服务器接收的响应相同。 请按照以下步骤操作: -

您不需要为每个请求使用不同类型的适配器,只需使用默认的Gson转换器工厂创建改造: -

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

现在您需要为API请求定义服务,如下所示: -

public class ArticleService{
   @GET("endpoint")//What ever is your request type
   Call<Response> getArticals(/** body query param or other required data**// )
}

之后您要求创建将是这样的: -

ArticleService service = retrofit.create(ArticleService.class);