无法使用retrofit2解析api

Posted

技术标签:

【中文标题】无法使用retrofit2解析api【英文标题】:Can't parse api using retrofit2 【发布时间】:2021-10-26 13:03:50 【问题描述】:

我正在尝试使用 retorfit2 解析 https://favqs.com/api/ 首先,我想至少从 json 中提取日期

@Generated("jsonschema2pojo")
public class Example 

    @SerializedName("qotd_date")
    @Expose
    private String qotdDate;
    @SerializedName("quote")
    @Expose
    private Quote quote;

    public String getQotdDate() 
        return qotdDate;
    

    public void setQotdDate(String qotdDate) 
        this.qotdDate = qotdDate;
    

    public Quote getQuote() 
        return quote;
    

    public void setQuote(Quote quote) 
        this.quote = quote;
    


类引用:

@Generated("jsonschema2pojo")
public class Quote 

    @SerializedName("id")
    @Expose
    private Integer id;
    @SerializedName("dialogue")
    @Expose
    private Boolean dialogue;
    @SerializedName("private")
    @Expose
    private Boolean _private;
    @SerializedName("tags")
    @Expose
    private List<Object> tags = null;
    @SerializedName("url")
    @Expose
    private String url;
    @SerializedName("favorites_count")
    @Expose
    private Integer favoritesCount;
    @SerializedName("upvotes_count")
    @Expose
    private Integer upvotesCount;
    @SerializedName("downvotes_count")
    @Expose
    private Integer downvotesCount;
    @SerializedName("author")
    @Expose
    private String author;
    @SerializedName("author_permalink")
    @Expose
    private String authorPermalink;
    @SerializedName("body")
    @Expose
    private String body;

    public Integer getId() 
        return id;
    

    public void setId(Integer id) 
        this.id = id;
    

    public Boolean getDialogue() 
        return dialogue;
    

    public void setDialogue(Boolean dialogue) 
        this.dialogue = dialogue;
    

    public Boolean getPrivate() 
        return _private;
    

    public void setPrivate(Boolean _private) 
        this._private = _private;
    

    public List<Object> getTags() 
        return tags;
    

    public void setTags(List<Object> tags) 
        this.tags = tags;
    

    public String getUrl() 
        return url;
    

    public void setUrl(String url) 
        this.url = url;
    

    public Integer getFavoritesCount() 
        return favoritesCount;
    

    public void setFavoritesCount(Integer favoritesCount) 
        this.favoritesCount = favoritesCount;
    

    public Integer getUpvotesCount() 
        return upvotesCount;
    

    public void setUpvotesCount(Integer upvotesCount) 
        this.upvotesCount = upvotesCount;
    

    public Integer getDownvotesCount() 
        return downvotesCount;
    

    public void setDownvotesCount(Integer downvotesCount) 
        this.downvotesCount = downvotesCount;
    

    public String getAuthor() 
        return author;
    

    public void setAuthor(String author) 
        this.author = author;
    

    public String getAuthorPermalink() 
        return authorPermalink;
    

    public void setAuthorPermalink(String authorPermalink) 
        this.authorPermalink = authorPermalink;
    

    public String getBody() 
        return body;
    

    public void setBody(String body) 
        this.body = body;
    


类客户:

public interface Client 

    @GET("qotd_date")
    Call<List<Example>> reposForUser();

类 MyAdapter:

public class MyAdapter extends ArrayAdapter<Example> 

    private Context context;
    private List<Example> values;

    public MyAdapter(Context context, List<Example> values) 
        super(context, R.layout.list_item_pagination, values);

        this.context = context;
        this.values = values;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        View row = convertView;

        if (row == null) 
            LayoutInflater inflater =
                    (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.list_item_pagination, parent, false);
        

        TextView textView = (TextView) row.findViewById(R.id.list_item_pagination_text);

        Example item = values.get(position);
        String message = item.getQotdDate();
        textView.setText(message);

        return row;
    

类 MainActivity:

public class MainActivity extends AppCompatActivity 

    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.pagination_list);


        Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl("https://favqs.com/api/")
                .addConverterFactory(GsonConverterFactory.create());

        Retrofit retrofit = builder.build();

        Client client = retrofit.create(Client.class);
        Call<List<Example>> call = client.reposForUser();

        call.enqueue(new Callback<List<Example>>() 
            @Override
            public void onResponse(Call<List<Example>> call, Response<List<Example>> response) 
                List<Example> repos = response.body();

                listView.setAdapter(new MyAdapter(MainActivity.this, repos));
            

            @Override
            public void onFailure(Call<List<Example>> call, Throwable t) 
                Toast.makeText(MainActivity.this, "error :(", Toast.LENGTH_SHORT).show();
            
        );
    

应用程序启动但未在 listView 中输出任何内容。 Toast 显示消息:“error :(”

可能问题出现在这部分代码中:

call.enqueue(new Callback<List<Example>>() 
    @Override
    public void onResponse(Call<List<Example>> call, Response<List<Example>> response) 
        List<Example> repos = response.body();
        Log.d("mylog1", String.valueOf(repos));
        Log.d("mylog1","mylog");

        listView.setAdapter(new MyAdapter(MainActivity.this, repos));
    

    @Override
    public void onFailure(Call<List<Example>> call, Throwable t) 
        Toast.makeText(MainActivity.this, "error :(", Toast.LENGTH_SHORT).show();
        t.printStackTrace();
    
);

call.enqueue (new Callback &lt;List &lt;Example&gt;&gt; () 之后的代码没有开始执行

方法开始onFailure(Call&lt;List&lt;Example&gt;&gt; call, Throwable t)

字符串t.printStackTrace(); 给出错误信息:

W/System.err: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $
W/System.err:     at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1562)
        at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1403)
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:592)
        at com.google.gson.stream.JsonReader.peek(JsonReader.java:424)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:74)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
        at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243)
W/System.err:     at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:174)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
W/System: A resource failed to call close. 
    A resource failed to call close. 

【问题讨论】:

我认为您的服务不正确“qotd_date”,请尝试下一个“qotd” @Manuel Mato,不幸的是,仍然出现错误 从您的调用中删除列表,因为端点 favqs.com/api/qotd 返回一个对象,而不是一个列表 @Manuel Mato,感谢您的回答!他帮了我很多。请以回复的形式提出您的评论,以便我接受 【参考方案1】:

从您的调用中删除列表,因为端点 favqs.com/api/qotd 返回一个对象,而不是一个列表

【讨论】:

以上是关于无法使用retrofit2解析api的主要内容,如果未能解决你的问题,请参考以下文章

使用Retrofit2解析XML。多个结果列表不起作用

改造无法正确解析正文

如何使用 Retrofit2 和 GSON 转换器解决“古怪”的 JSON API

如何使用 Retrofit2 处理嵌套 JsonObjects 的动态字段

无法在 Retrofit 2.0 android 中获取 json 字符串作为响应

从retrofit2和rxjava中的错误获取url