【发布时间】:2015-07-02 00:31:36
【问题描述】:
所以我正在尝试使用 Gson 和 Retrofit 解决我的自定义 TypeAdapter 的问题。我不断收到Expected BEGIN_OBJECT but was STRING 错误,但我不确定如何解决它。以前我收到Expected BEGIN_ARRAY but was STRING 错误,我解决了这个问题。我不确定它是否需要与这个新错误相同。我在下面列出了我的课程,感谢您提供任何帮助。这是我的 json 在这里的样子:http://pastie.org/private/bfo86iznldacbz10rtsdsg 主要问题是 json 中的多媒体字段。如果没有值,则为空字符串,如果有值,则返回包含 jsonobjects 的 jsonarray。
ArrayAdapter.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
public class ArrayAdapter<T> extends TypeAdapter<List<T>> {
private Class<T> adapterclass;
public ArrayAdapter(Class<T> adapterclass) {
this.adapterclass = adapterclass;
}
public List<T> read(JsonReader reader) throws IOException {
List<T> list = new ArrayList<T>();
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new ArrayAdapterFactory())
.create();
if (reader.peek() == JsonToken.STRING) {
T inning = gson.fromJson(reader, adapterclass);
list.add(inning);
} else if (reader.peek() == JsonToken.BEGIN_ARRAY) {
reader.beginArray();
while (reader.hasNext()) {
T inning = gson.fromJson(reader, adapterclass);
list.add(inning);
}
reader.endArray();
} else if (reader.peek() == JsonToken.BEGIN_OBJECT) {
reader.beginObject();
while(reader.hasNext()) {
}
}
return list;
}
public void write(JsonWriter writer, List<T> value) throws IOException {
}
}
ArraryAdapterFactory
import java.lang.reflect.ParameterizedType;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
public class ArrayAdapterFactory implements TypeAdapterFactory {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
TypeAdapter<T> typeAdapter = null;
try {
if (type.getRawType() == List.class)
typeAdapter = new ArrayAdapter(
(Class) ((ParameterizedType) type.getType())
.getActualTypeArguments()[0]);
} catch (Exception e) {
e.printStackTrace();
}
return typeAdapter;
}
}
Times.java
public class NYTimes {
// uses the new york times api
// gets the top stores on the nytimes homepage
private static final String API_URL = "http://api.nytimes.com/svc/news/v3/content/all/all";
static Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ArrayAdapterFactory()).create();
private static final RestAdapter REST_ADAPTER = new RestAdapter.Builder()
.setConverter(new GsonConverter(gson))
.setEndpoint(API_URL)
.build();
private static final NYTimesService SERVICE = REST_ADAPTER.create(NYTimesService.class);
public static NYTimesService getService() {
return SERVICE;
}
}
POJO 类
News.java
public class News {
@Expose
private String status;
@Expose
private String copyright;
@SerializedName("num_results")
@Expose
private Integer numResults;
@Expose
private List<Result> results = new ArrayList<Result>();
/**
*
* @return
* The status
*/
public String getStatus() {
return status;
}
/**
*
* @param status
* The status
*/
public void setStatus(String status) {
this.status = status;
}
/**
*
* @return
* The copyright
*/
public String getCopyright() {
return copyright;
}
/**
*
* @param copyright
* The copyright
*/
public void setCopyright(String copyright) {
this.copyright = copyright;
}
/**
*
* @return
* The numResults
*/
public Integer getNumResults() {
return numResults;
}
/**
*
* @param numResults
* The num_results
*/
public void setNumResults(Integer numResults) {
this.numResults = numResults;
}
/**
*
* @return
* The results
*/
public List<Result> getResults() {
return results;
}
/**
*
* @param results
* The results
*/
public void setResults(List<Result> results) {
this.results = results;
}
}
Result.java
public class Result {
@Expose
private String section;
@Expose
private String subsection;
@Expose
private String title;
@SerializedName("abstract")
@Expose
private String _abstract;
@Expose
private String url;
@Expose
private String byline;
@SerializedName("thumbnail_standard")
@Expose
private String thumbnailStandard;
@SerializedName("item_type")
@Expose
private String itemType;
@Expose
private String source;
@SerializedName("updated_date")
@Expose
private String updatedDate;
@SerializedName("created_date")
@Expose
private String createdDate;
@SerializedName("published_date")
@Expose
private String publishedDate;
@SerializedName("material_type_facet")
@Expose
private String materialTypeFacet;
@Expose
private String kicker;
@Expose
private String subheadline;
@SerializedName("des_facet")
@Expose
private List<String> desFacet = new ArrayList<>();
@SerializedName("org_facet")
@Expose
private List<String> orgFacet = new ArrayList<>();
@SerializedName("per_facet")
@Expose
private List<String> perFacet = new ArrayList<>();
@SerializedName("geo_facet")
@Expose
private List<String> geoFacet = new ArrayList<>();
@SerializedName("related_urls")
@Expose
private Object relatedUrls;
@Expose
private List<Multimedium> multimedia;
/**
*
* @return
* The section
*/
public String getSection() {
return section;
}
/**
*
* @param section
* The section
*/
public void setSection(String section) {
this.section = section;
}
/**
*
* @return
* The subsection
*/
public String getSubsection() {
return subsection;
}
/**
*
* @param subsection
* The subsection
*/
public void setSubsection(String subsection) {
this.subsection = subsection;
}
/**
*
* @return
* The title
*/
public String getTitle() {
return title;
}
/**
*
* @param title
* The title
*/
public void setTitle(String title) {
this.title = title;
}
/**
*
* @return
* The _abstract
*/
public String getAbstract() {
return _abstract;
}
/**
*
* @param _abstract
* The abstract
*/
public void setAbstract(String _abstract) {
this._abstract = _abstract;
}
/**
*
* @return
* The url
*/
public String getUrl() {
return url;
}
/**
*
* @param url
* The url
*/
public void setUrl(String url) {
this.url = url;
}
/**
*
* @return
* The byline
*/
public String getByline() {
return byline;
}
/**
*
* @param byline
* The byline
*/
public void setByline(String byline) {
this.byline = byline;
}
/**
*
* @return
* The thumbnailStandard
*/
public String getThumbnailStandard() {
return thumbnailStandard;
}
/**
*
* @param thumbnailStandard
* The thumbnail_standard
*/
public void setThumbnailStandard(String thumbnailStandard) {
this.thumbnailStandard = thumbnailStandard;
}
/**
*
* @return
* The itemType
*/
public String getItemType() {
return itemType;
}
/**
*
* @param itemType
* The item_type
*/
public void setItemType(String itemType) {
this.itemType = itemType;
}
/**
*
* @return
* The source
*/
public String getSource() {
return source;
}
/**
*
* @param source
* The source
*/
public void setSource(String source) {
this.source = source;
}
/**
*
* @return
* The updatedDate
*/
public String getUpdatedDate() {
return updatedDate;
}
/**
*
* @param updatedDate
* The updated_date
*/
public void setUpdatedDate(String updatedDate) {
this.updatedDate = updatedDate;
}
/**
*
* @return
* The createdDate
*/
public String getCreatedDate() {
return createdDate;
}
/**
*
* @param createdDate
* The created_date
*/
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
/**
*
* @return
* The publishedDate
*/
public String getPublishedDate() {
return publishedDate;
}
/**
*
* @param publishedDate
* The published_date
*/
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
/**
*
* @return
* The materialTypeFacet
*/
public String getMaterialTypeFacet() {
return materialTypeFacet;
}
/**
*
* @param materialTypeFacet
* The material_type_facet
*/
public void setMaterialTypeFacet(String materialTypeFacet) {
this.materialTypeFacet = materialTypeFacet;
}
/**
*
* @return
* The kicker
*/
public String getKicker() {
return kicker;
}
/**
*
* @param kicker
* The kicker
*/
public void setKicker(String kicker) {
this.kicker = kicker;
}
/**
*
* @return
* The subheadline
*/
public String getSubheadline() {
return subheadline;
}
/**
*
* @param subheadline
* The subheadline
*/
public void setSubheadline(String subheadline) {
this.subheadline = subheadline;
}
/**
*
* @return
* The desFacet
*/
public List<String> getDesFacet() {
return desFacet;
}
/**
*
* @param desFacet
* The des_facet
*/
public void setDesFacet(List<String> desFacet) {
this.desFacet = desFacet;
}
/**
*
* @return
* The orgFacet
*/
public List<String> getOrgFacet() {
return orgFacet;
}
/**
*
* @param orgFacet
* The org_facet
*/
public void setOrgFacet(List<String> orgFacet) {
this.orgFacet = orgFacet;
}
/**
*
* @return
* The perFacet
*/
public List<String> getPerFacet() {
return perFacet;
}
/**
*
* @param perFacet
* The per_facet
*/
public void setPerFacet(List<String> perFacet) {
this.perFacet = perFacet;
}
/**
*
* @return
* The geoFacet
*/
public List<String> getGeoFacet() {
return geoFacet;
}
/**
*
* @param geoFacet
* The geo_facet
*/
public void setGeoFacet(List<String> geoFacet) {
this.geoFacet = geoFacet;
}
/**
*
* @return
* The relatedUrls
*/
public Object getRelatedUrls() {
return relatedUrls;
}
/**
*
* @param relatedUrls
* The related_urls
*/
public void setRelatedUrls(Object relatedUrls) {
this.relatedUrls = relatedUrls;
}
/**
*
* @return
* The multimedia
*/
public List<Multimedium> getMultimedia() {
return multimedia;
}
/**
*
* @param multimedia
* The multimedia
*/
public void setMultimedia(List<Multimedium> multimedia) {
this.multimedia = multimedia;
}
}
多媒体.java
public class Multimedium {
@Expose
private String url;
@Expose
private String format;
@Expose
private Integer height;
@Expose
private Integer width;
@Expose
private String type;
@Expose
private String subtype;
@Expose
private Object caption;
@Expose
private Object copyright;
/**
*
* @return
* The url
*/
public String getUrl() {
return url;
}
/**
*
* @param url
* The url
*/
public void setUrl(String url) {
this.url = url;
}
/**
*
* @return
* The format
*/
public String getFormat() {
return format;
}
/**
*
* @param format
* The format
*/
public void setFormat(String format) {
this.format = format;
}
/**
*
* @return
* The height
*/
public Integer getHeight() {
return height;
}
/**
*
* @param height
* The height
*/
public void setHeight(Integer height) {
this.height = height;
}
/**
*
* @return
* The width
*/
public Integer getWidth() {
return width;
}
/**
*
* @param width
* The width
*/
public void setWidth(Integer width) {
this.width = width;
}
/**
*
* @return
* The type
*/
public String getType() {
return type;
}
/**
*
* @param type
* The type
*/
public void setType(String type) {
this.type = type;
}
/**
*
* @return
* The subtype
*/
public String getSubtype() {
return subtype;
}
/**
*
* @param subtype
* The subtype
*/
public void setSubtype(String subtype) {
this.subtype = subtype;
}
/**
*
* @return
* The caption
*/
public Object getCaption() {
return caption;
}
/**
*
* @param caption
* The caption
*/
public void setCaption(Object caption) {
this.caption = caption;
}
/**
*
* @return
* The copyright
*/
public Object getCopyright() {
return copyright;
}
/**
*
* @param copyright
* The copyright
*/
public void setCopyright(Object copyright) {
this.copyright = copyright;
}
}
我知道要处理很多代码,但我正在寻找任何帮助来解决这个问题,所以我尽量做到清楚。
【问题讨论】:
-
你的 JSON 是什么样子的?
-
@Onheiron 这是 json pastie.org/private/bfo86iznldacbz10rtsdsg 的一个示例,api 在返回的内容中是动态的。我遇到问题的部分是“多媒体”字段。如果为空,则作为字符串返回。如果它被填满,它会作为一个带有 jsonobjects 的 jsonarray 返回,如您所见。
-
您的 pojo 课程有问题。 json 有一个 jsonobject 但您正试图将其解析为字符串。如果您发布您的 json,我可以更有效地帮助您。
-
@savepopulation 我在帖子开头添加了一个链接作为编辑。问题是api是动态的。我试图解析的元素在为空时作为字符串返回,但在填充时作为 jsonarray 返回,其中包含 jsonobjects。该链接显示了填充元素时的 json 示例。我说的是“多媒体”元素。
-
你可以通过 JSONObject category=jsonObject.optJSONObject("Category"); 来检查它是否是一个 json 对象。如果您的对象不为空,您可以获得它是一个对象,如果它为空,您可以将其用作 json 数组。但请注意不要将您的字符串作为空 json 对象发送。发送“”
标签: java android gson retrofit