使用改造将不一致的 JSON 解析为 POJO
Posted
技术标签:
【中文标题】使用改造将不一致的 JSON 解析为 POJO【英文标题】:Parse inconsistent JSON to POJO using retrofit 【发布时间】:2020-11-16 21:42:54 【问题描述】:我有一个 JSON 响应,其中包含多个 JSON 对象。有时这些 JsonObject 包含数据,有时这些 JsonObject 包含一个空字符串。因此,当我使用改造 gson 转换器解析对 POJO 的 JSON 响应时,它会抛出“java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $”。我不确定如何处理这种动态响应。
我的 JSON:
"assetDetails":
"id": "0-0-175244",
"rating": 5,
"duration": 3538,
"on_air": "true",
"content_owner": "ghuiiio",
"business_type": "premium_downloadable",
"age_rating": "A",
"title": "QWERTY",
"actors": [
"ABC",
"PQR"
],
"asset_type": 0,
"original_title": "QWERTY",
"directors": [
"jgdhisl"
],
"asset_subtype": "movie",
"drm_key_id": "1cba26eb-9d76-4275-9a5c-c651640dc929",
"subtitle_lang": [
"en"
],
"end_credits_start_s": "00:00:56",
"orderid": 0,
"extended":
"seo_title": "QWERTY",
"broadcast_state": "",
"music_directors": []
,
"season_details": "",
"description": "XYZ",
"genres": [
"id": "Thriller",
"value": "Thriller"
],
"release_date": "2020-06-27T00:00:00",
"subtitle_languages": [
"en"
],
"languages": [
"hi"
],
"audio_languages": [
"hi"
]
POJO:
public class PlaybackDetails
@SerializedName("assetDetails")
private AssetDetails assetDetails;
@SerializedName("watchHistoryDetails")
private WatchHistoryDetails watchHistoryDetails;
@SerializedName("trailerDetails")
private Object trailerDetails;
@SerializedName("keyOsDetails")
private KeyOsDetails keyOsDetails;
@SerializedName("entitlement")
private Entitlement entitlement;
@SerializedName("adDetails")
private AdDetails adDetails;
@SerializedName("showDetails")
private ShowDetails showDetails;
public void setAssetDetails(AssetDetails assetDetails)
this.assetDetails = assetDetails;
public AssetDetails getAssetDetails()
return assetDetails;
public void setWatchHistoryDetails(WatchHistoryDetails watchHistoryDetails)
this.watchHistoryDetails = watchHistoryDetails;
public WatchHistoryDetails getWatchHistoryDetails()
return watchHistoryDetails;
public void setTrailerDetails(Object trailerDetails)
this.trailerDetails = trailerDetails;
public Object getTrailerDetails()
return trailerDetails;
public void setKeyOsDetails(KeyOsDetails keyOsDetails)
this.keyOsDetails = keyOsDetails;
public KeyOsDetails getKeyOsDetails()
return keyOsDetails;
public void setEntitlement(Entitlement entitlement)
this.entitlement = entitlement;
public Entitlement getEntitlement()
return entitlement;
public void setAdDetails(AdDetails adDetails)
this.adDetails = adDetails;
public AdDetails getAdDetails()
return adDetails;
public void setShowDetails(ShowDetails showDetails)
this.showDetails = showDetails;
public ShowDetails getShowDetails()
return showDetails;
@Override
public String toString()
return
"PlaybackDetails" +
"convivaDetails = '" + convivaDetails + '\'' +
",assetDetails = '" + assetDetails + '\'' +
",watchHistoryDetails = '" + watchHistoryDetails + '\'' +
",trailerDetails = '" + trailerDetails + '\'' +
",keyOsDetails = '" + keyOsDetails + '\'' +
",entitlement = '" + entitlement + '\'' +
",adDetails = '" + adDetails + '\'' +
",showDetails = '" + showDetails + '\'' +
"";
public class AssetDetails
@SerializedName("asset_subtype")
private String assetSubtype;
@SerializedName("audio_languages")
private List<String> audioLanguages;
@SerializedName("subtitle_languages")
private List<String> subtitleLanguages;
@SerializedName("rating")
private int rating;
@SerializedName("description")
private String description;
@SerializedName("title")
private String title;
@SerializedName("drm_key_id")
private String drmKeyId;
@SerializedName("extended")
private Extended extended;
@SerializedName("duration")
private int duration;
@SerializedName("episode_number")
private int episodeNumber;
@SerializedName("video_url")
private VideoUrl videoUrl;
@SerializedName("subtitle_lang")
private List<String> subtitleLang;
@SerializedName("genres")
private List<GenresItem> genres;
@SerializedName("business_type")
private String businessType;
@SerializedName("asset_type")
private int assetType;
@SerializedName("tvshow")
private String tvshow;
@SerializedName("season")
private String season;
@SerializedName("id")
private String id;
@SerializedName("skip_available")
private SkipAvailable skipAvailable;
@SerializedName("cover_image")
private String coverImage;
@SerializedName("slug")
private String slug;
@SerializedName("season_details")
private SeasonDetails seasonDetails;
@SerializedName("original_title")
private String originalTitle;
@SerializedName("is_drm")
private int isDrm;
@SerializedName("languages")
private List<String> languages;
@SerializedName("list_image")
private String listImage;
@SerializedName("age_rating")
private String ageRating;
@SerializedName("orderid")
private int orderid;
@SerializedName("image_url")
private String imageUrl;
@SerializedName("end_credits_start_s")
private String endCreditsStartS;
@SerializedName("content_owner")
private String contentOwner;
@SerializedName("tags")
private List<String> tags;
@SerializedName("channels")
private List<ChannelsItem> channels;
@SerializedName("web_url")
private String webUrl;
@SerializedName("release_date")
private String releaseDate;
public void setAssetSubtype(String assetSubtype)
this.assetSubtype = assetSubtype;
public String getAssetSubtype()
return assetSubtype;
public void setAudioLanguages(List<String> audioLanguages)
this.audioLanguages = audioLanguages;
public List<String> getAudioLanguages()
return audioLanguages;
public void setSubtitleLanguages(List<String> subtitleLanguages)
this.subtitleLanguages = subtitleLanguages;
public List<String> getSubtitleLanguages()
return subtitleLanguages;
public void setRating(int rating)
this.rating = rating;
public int getRating()
return rating;
public void setDescription(String description)
this.description = description;
public String getDescription()
return description;
public void setTitle(String title)
this.title = title;
public String getTitle()
return title;
public void setDrmKeyId(String drmKeyId)
this.drmKeyId = drmKeyId;
public String getDrmKeyId()
return drmKeyId;
public void setExtended(Extended extended)
this.extended = extended;
public Extended getExtended()
return extended;
public void setDuration(int duration)
this.duration = duration;
public int getDuration()
return duration;
public void setEpisodeNumber(int episodeNumber)
this.episodeNumber = episodeNumber;
public int getEpisodeNumber()
return episodeNumber;
public void setVideoUrl(VideoUrl videoUrl)
this.videoUrl = videoUrl;
public VideoUrl getVideoUrl()
return videoUrl;
public void setSubtitleLang(List<String> subtitleLang)
this.subtitleLang = subtitleLang;
public List<String> getSubtitleLang()
return subtitleLang;
public void setGenres(List<GenresItem> genres)
this.genres = genres;
public List<GenresItem> getGenres()
return genres;
public void setBusinessType(String businessType)
this.businessType = businessType;
public String getBusinessType()
return businessType;
public void setAssetType(int assetType)
this.assetType = assetType;
public int getAssetType()
return assetType;
public void setTvshow(String tvshow)
this.tvshow = tvshow;
public String getTvshow()
return tvshow;
public void setSeason(String season)
this.season = season;
public String getSeason()
return season;
public void setId(String id)
this.id = id;
public String getId()
return id;
public void setSkipAvailable(SkipAvailable skipAvailable)
this.skipAvailable = skipAvailable;
public SkipAvailable getSkipAvailable()
return skipAvailable;
public void setCoverImage(String coverImage)
this.coverImage = coverImage;
public String getCoverImage()
return coverImage;
public void setSlug(String slug)
this.slug = slug;
public String getSlug()
return slug;
public void setSeasonDetails(SeasonDetails seasonDetails)
this.seasonDetails = seasonDetails;
public SeasonDetails getSeasonDetails()
return seasonDetails;
public void setOriginalTitle(String originalTitle)
this.originalTitle = originalTitle;
public String getOriginalTitle()
return originalTitle;
public void setIsDrm(int isDrm)
this.isDrm = isDrm;
public int getIsDrm()
return isDrm;
public void setLanguages(List<String> languages)
this.languages = languages;
public List<String> getLanguages()
return languages;
public void setListImage(String listImage)
this.listImage = listImage;
public String getListImage()
return listImage;
public void setAgeRating(String ageRating)
this.ageRating = ageRating;
public String getAgeRating()
return ageRating;
public void setOrderid(int orderid)
this.orderid = orderid;
public int getOrderid()
return orderid;
public void setImageUrl(String imageUrl)
this.imageUrl = imageUrl;
public String getImageUrl()
return imageUrl;
public void setEndCreditsStartS(String endCreditsStartS)
this.endCreditsStartS = endCreditsStartS;
public String getEndCreditsStartS()
return endCreditsStartS;
public void setContentOwner(String contentOwner)
this.contentOwner = contentOwner;
public String getContentOwner()
return contentOwner;
public void setTags(List<String> tags)
this.tags = tags;
public List<String> getTags()
return tags;
public void setChannels(List<ChannelsItem> channels)
this.channels = channels;
public List<ChannelsItem> getChannels()
return channels;
public void setWebUrl(String webUrl)
this.webUrl = webUrl;
public String getWebUrl()
return webUrl;
public void setReleaseDate(String releaseDate)
this.releaseDate = releaseDate;
public String getReleaseDate()
return releaseDate;
@Override
public String toString()
return
"AssetDetails" +
"asset_subtype = '" + assetSubtype + '\'' +
",audio_languages = '" + audioLanguages + '\'' +
",subtitle_languages = '" + subtitleLanguages + '\'' +
",rating = '" + rating + '\'' +
",description = '" + description + '\'' +
",title = '" + title + '\'' +
",drm_key_id = '" + drmKeyId + '\'' +
",extended = '" + extended + '\'' +
",duration = '" + duration + '\'' +
",episode_number = '" + episodeNumber + '\'' +
",video_url = '" + videoUrl + '\'' +
",subtitle_lang = '" + subtitleLang + '\'' +
",genres = '" + genres + '\'' +
",business_type = '" + businessType + '\'' +
",asset_type = '" + assetType + '\'' +
",tvshow = '" + tvshow + '\'' +
",season = '" + season + '\'' +
",id = '" + id + '\'' +
",skip_available = '" + skipAvailable + '\'' +
",cover_image = '" + coverImage + '\'' +
",slug = '" + slug + '\'' +
",season_details = '" + seasonDetails + '\'' +
",original_title = '" + originalTitle + '\'' +
",is_drm = '" + isDrm + '\'' +
",languages = '" + languages + '\'' +
",list_image = '" + listImage + '\'' +
",age_rating = '" + ageRating + '\'' +
",orderid = '" + orderid + '\'' +
",image_url = '" + imageUrl + '\'' +
",end_credits_start_s = '" + endCreditsStartS + '\'' +
",content_owner = '" + contentOwner + '\'' +
",tags = '" + tags + '\'' +
",channels = '" + channels + '\'' +
",web_url = '" + webUrl + '\'' +
",release_date = '" + releaseDate + '\'' +
"";
在上面的 JSON 中,season_details 可以是 JSONObject,也可以是空的。
【问题讨论】:
你能发布你的 POJO 吗?您应该使用TypeAdapter
(javadoc.io/doc/com.google.code.gson/gson/2.8.0/com/google/gson/…) 来解决给出错误的子对象的特定解析,但您需要知道如何处理“空字符串大小写”。
请粘贴各种json字符串。
【参考方案1】:
您可以使用自定义反序列化器来检查该值是否为真实对象,如果不是,则决定如何处理。
例如(用于任何类型):
public class StringOrObjectDeSerializer<T> implements JsonDeserializer<T>
// deserializer NOT registered with this Gson to prevent recursion!
private final Gson innerGson = new Gson();
@Override
public T deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException
if (json.isJsonObject())
return innerGson.fromJson(json, typeOfT);
// null or some other default value for non-json-objects
return null;
使用前注册即可,如:
Gson gson = new GsonBuilder()
.registerTypeAdapter(SeasonDetail.class, new StringOrObjectDeSerializer<>())
.create();
如果您需要知道如何使用 Retrofit 注册它,请参阅this post
【讨论】:
以上是关于使用改造将不一致的 JSON 解析为 POJO的主要内容,如果未能解决你的问题,请参考以下文章
这是在没有 get/set-ters 的情况下改造 POJO 的正确方法吗?