所以我正在尝试使用Gson和Retrofit解决我的自定义TypeAdapter问题。我一直收到Dog
错误,但我不确定如何解决它。以前我收到Expected BEGIN_OBJECT but was STRING
错误,我解决了这个问题。我不确定它是否需要与这个新错误相同。我在下面列出了我的课程,感谢任何帮助。这就是我的json在这里的样子:http://pastie.org/private/bfo86iznldacbz10rtsdsg主要问题是json中的多媒体字段。如果没有值,它是一个空字符串,但如果有值,则返回包含jsonobjects的jsonarray。
ArrayAdapter.java
Expected BEGIN_ARRAY but was STRING
ArraryAdapterFactory
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 {
}
}
Times.java
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;
}
}
POJO课程
News.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;
}
}
Result.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;
}
}
Multimedium.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;
}
}
我知道要通过很多代码,但我正在寻找任何帮助来解决这个问题,所以我想尽可能地清楚。
答案 0 :(得分:1)
我能够通过实施自定义JsonDeserializer
然后将其添加到RestAdapter
来获得解决方案,如下所示:
public class ResultsDeserializerJson implements JsonDeserializer<Result> {
@Override
public Result deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonElement titleElement = json.getAsJsonObject().get("title");
JsonElement multimediaElement = json.getAsJsonObject().get("multimedia");
if (multimediaElement.isJsonArray()) {
return new Result(
titleElement.toString(),
(Multimedia[]) context.deserialize(multimediaElement.getAsJsonArray(), Multimedia[].class));
} else if (multimediaElement.getAsString().equals("")) {
Multimedia multimedia = new Multimedia();
multimedia.setFormat("");
multimedia.setUrl("");
return new Result(titleElement.toString(), multimedia);
} else {
Log.d("ResultsDeserializerJson", multimediaElement.toString());
throw new JsonParseException("Unsupported type of multimedia element");
}
}
}
在Result.java
内部我添加了以下构造函数(请注意,您可以为section,subsection等添加更多参数):
public Result(String title, Multimedia ... multimedia) {
this.mTitle = title.replace("\"", "");;
mMultimedia = Arrays.asList(multimedia);
}
然后我的RestAdapter
执行以下操作:
private NYTimesService() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Result.class, new ResultsDeserializerJson()).create();
mAsyncRestAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL)
.setConverter(new GsonConverter(gson))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addEncodedQueryParam("api-key", API_KEY);
}
})
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
}
我创建了一个自定义应用程序以使其正常工作,并且存储库在这里是开源的:
这仍然是一个hackish解决方案,我觉得它不是最优的,但我能够在我找到解决方案时得到以下内容: