Question

I have a REST service which returns data that looks like this:

[
    { bookmark object json here },
    { bookmark object json here },
    { bookmark object json here },
    ...
]

My REST client class looks like this:

@Rest(rootUrl = Constants.ApiConfig.API_ROOT, converters = {MappingJackson2HttpMessageConverter.class})
public interface RestApiClient {
    @Get("/bookmark/read?id={identifier}")
    public BookmarkList getBookmarks(String identifier);
}

BookmarkList looks like this:

public class BookmarkList {
    List<Bookmark> bookmarks;

    @JsonValue
    public List<Bookmark> getBookmarks() {
        return bookmarks;
    }

    @JsonCreator
    public void BookmarkList(@NotNull List<Bookmark> bookmarks) {
        this.bookmarks = bookmarks;
    }
}

However, when I utilize this setup, I get the following error:

Could not read JSON: Can not deserialize instance of com.whatever.entity.BookmarkList out of START_ARRAY token

What I want is something like the EventList example at https://github.com/excilys/androidannotations/wiki/Rest-API#get, but that doesn't seem to work for me out of the box.

Is there a way to get this working?

Était-ce utile?

La solution

Ho... We have to update this part of documentation. The wrapper solution works but doesn't fit APIs.

If you're looking at the generated code for @Get("url") MyReturnedType testService(), you should see something like this :

return restTemplate.exchange(rootUrl.concat("url"), //
    HttpMethod.GET, //
    null, //
    MyReturnedType.class, //
    urlVariables)//
  .getBody();

The returned class is injected as a parameter of exchange call. In case of generics collection (like List<MyReturnedType>), we can't inject List.class because of type checking in the return of exchange method.

However, you should be able to use this little trick in your @Rest annotated method :

public class BookmarkList extends List<Bookmark> {
}

Autres conseils

I think I misunderstood the example at https://github.com/excilys/androidannotations/wiki/Rest-API#get. I think the array still must be wrapped inside a JSON object in that example (It'd be nice if they included example JSON data).

The data the service I'm connecting to does not return an object wrapping the array like that, so, I altered the REST client to look like this:

@Rest(rootUrl = Constants.ApiConfig.API_ROOT, converters = {MappingJackson2HttpMessageConverter.class})
public interface RestApiClient {
    @Get("/bookmark/read?id={identifier}")
    public ArrayNode getBookmarks(String identifier);
}

And I wrote a method in another class to iterate the ArrayNode and build the bookmarks:

public List<Bookmark> getBookmarks(Content content) {
    ArrayList<Bookmark> bookmarks = new ArrayList<Bookmark>();
    ArrayNode bookmarksData = apiClient.getBookmarks(content.getAcid());

    for(JsonNode bookmarkData : bookmarksData) {
        Bookmark bookmark = objectMapper.convertValue(bookmarkData, Bookmark.class);
        bookmarks.add(bookmark);
    }
    return bookmarks;
}

So it's not as convenient (I had to write more code myself), but I got it working.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top