Search code examples
javaandroidretrofit2pojo

Retrofit conversion issue - how to correctly create POJO class for concrete JSON:


I'm new to android and building an app that loads data from REST API using Retrofit library. I managed to get it worked previously but now when I added some more variables to my POJO class, the Retrofit seems to have conversion issues. It goes to "OnFailure" and the error is not of type IOException. I think there might be problem with the list of Lecture objects.

This is the sample of source JSON:

[  
   {  
      "id":1603,
      "date":"2018-09-11T22:12:59",
      "date_gmt":"2018-09-11T20:12:59",
      "guid":{  
         "rendered":"https:\/\/get-splashed.cz\/?p=1603"
      },
      "modified":"2018-09-11T22:22:01",
      "modified_gmt":"2018-09-11T20:22:01",
      "slug":"stein-and-meredith",
      "status":"publish",
      "type":"post",
      "link":"https:\/\/get-splashed.cz\/speakers\/stein-and-meredith",
      "title":{  
         "rendered":"Stein and Meredith"
      },
      "content":{  
         "rendered":"Animation and Games. Whatever your experience",
         "protected":false
      },
      "excerpt":{  
         "rendered":"Head of Compositing",
         "protected":false
      },
      "author":1,
      "featured_media":1606,
      "comment_status":"open",
      "ping_status":"open",
      "sticky":false,
      "template":"",
      "format":"standard",
      "meta":[  

      ],
      "categories":[  
         2
      ],
      "tags":[  

      ],
      "acf":{  
         "role":"",
         "job":"<b>Escape Studios<\/b>",
         "social":false,
         "speaker_slider_shortcode":"[rev_slider alias=\"escape\"]",
         "o_prednasce":[  
            {  
               "nazev_prednasky":"Creating a killer showreel: advice & tips for VFX, Animation & Games",
               "den_prednasky":"nedele",
               "cas_prednasky":"17:30",
               "typ":"P\u0159edn\u00e1\u0161ka",
               "misto_konani":"Main Hall",
               "doba_trvani":"60",
               "prave_probiha":""
            }
         ]
      }
   },
   {  
      "id":1452,
      "date":"2018-08-13T22:41:19",
      "date_gmt":"2018-08-13T20:41:19",
      "guid":{  
         "rendered":"https:\/\/get-splashed.cz\/?p=1452"
      },
      "modified":"2018-08-14T11:27:11",
      "modified_gmt":"2018-08-14T09:27:11",
      "slug":"jan-jinda",
      "status":"publish",
      "type":"post",
      "link":"https:\/\/get-splashed.cz\/speakers\/jan-jinda",
      "title":{  
         "rendered":"Jan Jinda"
      },
      "content":{  
         "rendered":"<p>Czech born London based 3D Generalist",
         "protected":false
      },
      "excerpt":{  
         "rendered":"Czech born London based",
         "protected":false
      },
      "author":1,
      "featured_media":1453,
      "comment_status":"open",
      "ping_status":"open",
      "sticky":false,
      "template":"",
      "format":"standard",
      "meta":[  

      ],
      "categories":[  
         2
      ],
      "tags":[  

      ],
      "acf":{  
         "role":"Senior Build TD",
         "job":"<b>Dneg<\/b>",
         "social":[  
            {  
               "odkaz":"https:\/\/www.facebook.com\/jan.jinda",
               "socialni_sit":"facebook"
            },
            {  
               "odkaz":"https:\/\/www.linkedin.com\/in\/janjinda\/",
               "socialni_sit":"linkedin"
            }
         ],
         "speaker_slider_shortcode":"[rev_slider alias=\"jinda\"]",
         "o_prednasce":[  
            {  
               "nazev_prednasky":"Building massive Jaegers for PR2",
               "den_prednasky":"sobota",
               "cas_prednasky":"15:00",
               "typ":"P\u0159edn\u00e1\u0161ka",
               "misto_konani":"Main Hall",
               "doba_trvani":"60",
               "prave_probiha":""
            }
         ]
      }
   }
]

And my POJO class:

import com.google.gson.annotations.SerializedName;

import java.util.List;

public class Speaker {

    @SerializedName("id")
    private int mId;

    @SerializedName("title")
    private Title mTitle;

    @SerializedName("acf")
    private Acf mAcf;

    @SerializedName("featured_media")
    private int mMediaId;

    @SerializedName("content")
    private Content mContent;

    String mImageUrl = "";

    // indicator if the speaker is fake - zig-zag layout
    private boolean mFakeSpeaker = false;

    public Speaker(int id, Title title, Acf acf, int mediaId, String imageUrl, boolean fakeSpeaker) {
        mId = id;
        mTitle = title;
        mAcf = acf;
        mImageUrl = imageUrl;
        mMediaId = mediaId;
        mFakeSpeaker = fakeSpeaker;
    }

    public int getId() {
        return mId;
    }

    public Title getTitle() {
        return mTitle;
    }

    public Acf getAcf() {
        return mAcf;
    }

    public int getMediaId() {
        return mMediaId;
    }

    public String getImageUrl() {
        return mImageUrl;
    }

    public void setImageUrl(String imageUrl) {
        mImageUrl = imageUrl;
    }

    public boolean getIsFakeSpeaker() {
        return mFakeSpeaker;
    }

    public void setIsFakeSpeaker(boolean isFakeSpeaker) {
        mFakeSpeaker = isFakeSpeaker;
    }

    public Content getContent() {
        return mContent;
    }

    public class Title {

        @SerializedName("rendered")
        private String mName;

        public Title(String name) {
            mName = name;
        }

        public String getName() {
            return mName;
        }
    }

    public class Acf {
        @SerializedName("role")
        private String mRole;

        @SerializedName("job")
        private String mCompany;

        @SerializedName("o_prednasce")
        private List<Lecture> mLectures;


        public Acf(String role, String company, List<Lecture> lectures) {
            mRole = role;
            mCompany = company;
            mLectures = lectures;
        }

        public String getRole() {
            return mRole;
        }

        public String getCompany() {
            return mCompany;
        }

        public List<Lecture> getLectures() {
            return mLectures;
        }

        public class Lecture {

            @SerializedName("nazev_prednasky")
            private String mLectureName;

            @SerializedName("den_prednasky")
            private String mLectureDay;

            @SerializedName("cas_prednasky")
            private String mLectureTime;

            public Lecture(String lectureName, String lectureDay, String lectureTime) {
                mLectureName = lectureName;
                mLectureDay = lectureDay;
                mLectureTime = lectureTime;
            }

            public String getLectureName() {
                return mLectureName;
            }

            public String getLectureDay() {
                return mLectureDay;
            }

            public String getLectureTime() {
                return mLectureTime;
            }
        }
    }

    public class Content {

        @SerializedName("rendered")
        private String mDescription;

        public Content(String description) {
            mDescription = description;
        }

        public String getDescription() {
            return mDescription;
        }
    }
}

The code worked until I added the Lecture class. Now I can not figure out what issue could be here.

EDIT: After loging the type of error in Retrofit's onFailure method:

            public void onFailure(Call<List<Speaker>> call, Throwable t) {

                if (t instanceof IOException) {
                    Log.v("RetrofitSplash", "No internet connection");
                } else {
                    Log.v("RetrofitSplash", "conversion issue! " + t.getMessage());
                }
            }

I found out there is an issue: "Expected BEGIN_ARRAY but was BOOLEAN at line 1 column 46857 path $[10].acf.o_prednasce"

And I looked to the JSON again and found out there is a field "acf.o_prednasce" that in one case instead of being array is "false" i.e. boolean.

See bigger sample of JSON:

[  
   {  
      "id":1603,
      "date":"2018-09-11T22:12:59",
      "date_gmt":"2018-09-11T20:12:59",
      "guid":{  
         "rendered":"https:\/\/get-splashed.cz\/?p=1603"
      },
      "modified":"2018-09-11T22:22:01",
      "modified_gmt":"2018-09-11T20:22:01",
      "slug":"stein-and-meredith",
      "status":"publish",
      "type":"post",
      "link":"https:\/\/get-splashed.cz\/speakers\/stein-and-meredith",
      "title":{  
         "rendered":"Stein and Meredith"
      },
      "content":{  
         "rendered":"Animation and Games. Whatever your experience",
         "protected":false
      },
      "excerpt":{  
         "rendered":"Head of Compositing",
         "protected":false
      },
      "author":1,
      "featured_media":1606,
      "comment_status":"open",
      "ping_status":"open",
      "sticky":false,
      "template":"",
      "format":"standard",
      "meta":[  

      ],
      "categories":[  
         2
      ],
      "tags":[  

      ],
      "acf":{  
         "role":"",
         "job":"<b>Escape Studios<\/b>",
         "social":false,
         "speaker_slider_shortcode":"[rev_slider alias=\"escape\"]",
         "o_prednasce":[  
            {  
               "nazev_prednasky":"Creating a killer showreel: advice & tips for VFX, Animation & Games",
               "den_prednasky":"nedele",
               "cas_prednasky":"17:30",
               "typ":"P\u0159edn\u00e1\u0161ka",
               "misto_konani":"Main Hall",
               "doba_trvani":"60",
               "prave_probiha":""
            }
         ]
      }
   },
   {  
      "id":1452,
      "date":"2018-08-13T22:41:19",
      "date_gmt":"2018-08-13T20:41:19",
      "guid":{  
         "rendered":"https:\/\/get-splashed.cz\/?p=1452"
      },
      "modified":"2018-08-14T11:27:11",
      "modified_gmt":"2018-08-14T09:27:11",
      "slug":"jan-jinda",
      "status":"publish",
      "type":"post",
      "link":"https:\/\/get-splashed.cz\/speakers\/jan-jinda",
      "title":{  
         "rendered":"Jan Jinda"
      },
      "content":{  
         "rendered":"<p>Czech born London based 3D Generalist",
         "protected":false
      },
      "excerpt":{  
         "rendered":"Czech born London based",
         "protected":false
      },
      "author":1,
      "featured_media":1453,
      "comment_status":"open",
      "ping_status":"open",
      "sticky":false,
      "template":"",
      "format":"standard",
      "meta":[  

      ],
      "categories":[  
         2
      ],
      "tags":[  

      ],
      "acf":{  
         "role":"Senior Build TD",
         "job":"<b>Dneg<\/b>",
         "social":[  
            {  
               "odkaz":"https:\/\/www.facebook.com\/jan.jinda",
               "socialni_sit":"facebook"
            },
            {  
               "odkaz":"https:\/\/www.linkedin.com\/in\/janjinda\/",
               "socialni_sit":"linkedin"
            }
         ],
         "speaker_slider_shortcode":"[rev_slider alias=\"jinda\"]",
         "o_prednasce":[  
            {  
               "nazev_prednasky":"Building massive Jaegers for PR2",
               "den_prednasky":"sobota",
               "cas_prednasky":"15:00",
               "typ":"P\u0159edn\u00e1\u0161ka",
               "misto_konani":"Main Hall",
               "doba_trvani":"60",
               "prave_probiha":""
            }
         ]
      }
   },
  {  
      "id":855,
      "date":"2018-05-02T23:21:11",
      "date_gmt":"2018-05-02T21:21:11",
      "guid":{  
         "rendered":"http:\/\/get-splashed.cz\/?p=855"
      },
      "modified":"2018-09-14T22:15:38",
      "modified_gmt":"2018-09-14T20:15:38",
      "slug":"talk-info-will-be-soon",
      "status":"publish",
      "type":"post",
      "link":"https:\/\/get-splashed.cz\/nezarazene\/talk-info-will-be-soon",
      "title":{  
         "rendered":"Speaker soon"
      },
      "content":{  
         "rendered":"",
         "protected":false
      },
      "excerpt":{  
         "rendered":"",
         "protected":false
      },
      "author":1,
      "featured_media":863,
      "comment_status":"open",
      "ping_status":"open",
      "sticky":false,
      "template":"",
      "format":"standard",
      "meta":[  

      ],
      "categories":[  
         1
      ],
      "tags":[  

      ],
      "acf":{  
         "role":"",
         "job":"",
         "social":false,
         "speaker_slider_shortcode":"",
         "o_prednasce":false
      }
   }
]

Solution

  • In the end I found the solution myself: as the field "acf.o_prednasce" in JSON was in one case a boolean and in the rest of cases an array, I filtered the API response by field "category" to get one type of this field in one response.