出于某种原因,我无法将其转换为POJO。我正在尝试的电话是这样的:
NewsEntities newsEntities = new Gson().fromJson(jsonString, NewsEntities.class);
神秘之处在于json不在数组中。我认为这是一个jsonObject。 jsonString为here
我在android中遇到的错误是:
Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 1006 path $.results[0].org_facet
02-24 23:42:49.955 15463-15531/news.myapp.com.technewssample W/System.err: at com.google.gson.stream.JsonReader.nextString(JsonReader.java:831)
02-24 23:42:49.955 15463-15531/news.myapp.com.technewssample W/System.err: at com.google.gson.internal.bind.TypeAdapters$16.read(TypeAdapters.java:422)
02-24 23:42:49.955 15463-15531/news.myapp.com.technewssample W/System.err: at com.google.gson.internal.bind.TypeAdapters$16.read(TypeAdapters.java:410)
02-24 23:42:49.955 15463-15531/news.myapp.com.technewssample W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116)
02-24 23:42:49.956 15463-15531/news.myapp.com.technewssample W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(Reflect
newsEntities类本身看起来像这样,我只是从http://www.jsonschema2pojo.org/:
创建 public class NewsEntities implements Parcelable
{
@SerializedName("status")
@Expose
private String status;
@SerializedName("copyright")
@Expose
private String copyright;
@SerializedName("section")
@Expose
private String section;
@SerializedName("last_updated")
@Expose
private String lastUpdated;
@SerializedName("num_results")
@Expose
private Integer numResults;
@SerializedName("results")
@Expose
private List<Result> results = null;
public final static Parcelable.Creator<NewsEntities> CREATOR = new Creator<NewsEntities>() {
@SuppressWarnings({
"unchecked"
})
public NewsEntities createFromParcel(Parcel in) {
NewsEntities instance = new NewsEntities();
instance.status = ((String) in.readValue((String.class.getClassLoader())));
instance.copyright = ((String) in.readValue((String.class.getClassLoader())));
instance.section = ((String) in.readValue((String.class.getClassLoader())));
instance.lastUpdated = ((String) in.readValue((String.class.getClassLoader())));
instance.numResults = ((Integer) in.readValue((Integer.class.getClassLoader())));
in.readList(instance.results, (Result.class.getClassLoader()));
return instance;
}
public NewsEntities[] newArray(int size) {
return (new NewsEntities[size]);
}
}
;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCopyright() {
return copyright;
}
public void setCopyright(String copyright) {
this.copyright = copyright;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Integer getNumResults() {
return numResults;
}
public void setNumResults(Integer numResults) {
this.numResults = numResults;
}
public List<Result> getResults() {
return results;
}
public void setResults(List<Result> results) {
this.results = results;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(status);
dest.writeValue(copyright);
dest.writeValue(section);
dest.writeValue(lastUpdated);
dest.writeValue(numResults);
dest.writeList(results);
}
public int describeContents() {
return 0;
}
}
更新:这是结果类:
public class Result implements Parcelable
{
@SerializedName("section")
@Expose
private String section;
@SerializedName("subsection")
@Expose
private String subsection;
@SerializedName("title")
@Expose
private String title;
@SerializedName("abstract")
@Expose
private String _abstract;
@SerializedName("url")
@Expose
private String url;
@SerializedName("byline")
@Expose
private String byline;
@SerializedName("item_type")
@Expose
private String itemType;
@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;
@SerializedName("kicker")
@Expose
private String kicker;
@SerializedName("des_facet")
@Expose
private List<String> desFacet = null;
@SerializedName("org_facet")
@Expose
private String orgFacet;
@SerializedName("per_facet")
@Expose
private String perFacet;
@SerializedName("geo_facet")
@Expose
private List<String> geoFacet = null;
@SerializedName("multimedia")
@Expose
private List<Multimedium> multimedia = null;
public final static Parcelable.Creator<Result> CREATOR = new Creator<Result>() {
@SuppressWarnings({
"unchecked"
})
public Result createFromParcel(Parcel in) {
Result instance = new Result();
instance.section = ((String) in.readValue((String.class.getClassLoader())));
instance.subsection = ((String) in.readValue((String.class.getClassLoader())));
instance.title = ((String) in.readValue((String.class.getClassLoader())));
instance._abstract = ((String) in.readValue((String.class.getClassLoader())));
instance.url = ((String) in.readValue((String.class.getClassLoader())));
instance.byline = ((String) in.readValue((String.class.getClassLoader())));
instance.itemType = ((String) in.readValue((String.class.getClassLoader())));
instance.updatedDate = ((String) in.readValue((String.class.getClassLoader())));
instance.createdDate = ((String) in.readValue((String.class.getClassLoader())));
instance.publishedDate = ((String) in.readValue((String.class.getClassLoader())));
instance.materialTypeFacet = ((String) in.readValue((String.class.getClassLoader())));
instance.kicker = ((String) in.readValue((String.class.getClassLoader())));
in.readList(instance.desFacet, (java.lang.String.class.getClassLoader()));
instance.orgFacet = ((String) in.readValue((String.class.getClassLoader())));
instance.perFacet = ((String) in.readValue((String.class.getClassLoader())));
in.readList(instance.geoFacet, (java.lang.String.class.getClassLoader()));
in.readList(instance.multimedia, (Multimedium.class.getClassLoader()));
return instance;
}
public Result[] newArray(int size) {
return (new Result[size]);
}
}
;
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getSubsection() {
return subsection;
}
public void setSubsection(String subsection) {
this.subsection = subsection;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAbstract() {
return _abstract;
}
public void setAbstract(String _abstract) {
this._abstract = _abstract;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getByline() {
return byline;
}
public void setByline(String byline) {
this.byline = byline;
}
public String getItemType() {
return itemType;
}
public void setItemType(String itemType) {
this.itemType = itemType;
}
public String getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(String updatedDate) {
this.updatedDate = updatedDate;
}
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
public String getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
public String getMaterialTypeFacet() {
return materialTypeFacet;
}
public void setMaterialTypeFacet(String materialTypeFacet) {
this.materialTypeFacet = materialTypeFacet;
}
public String getKicker() {
return kicker;
}
public void setKicker(String kicker) {
this.kicker = kicker;
}
public List<String> getDesFacet() {
return desFacet;
}
public void setDesFacet(List<String> desFacet) {
this.desFacet = desFacet;
}
public String getOrgFacet() {
return orgFacet;
}
public void setOrgFacet(String orgFacet) {
this.orgFacet = orgFacet;
}
public String getPerFacet() {
return perFacet;
}
public void setPerFacet(String perFacet) {
this.perFacet = perFacet;
}
public List<String> getGeoFacet() {
return geoFacet;
}
public void setGeoFacet(List<String> geoFacet) {
this.geoFacet = geoFacet;
}
public List<Multimedium> getMultimedia() {
return multimedia;
}
public void setMultimedia(List<Multimedium> multimedia) {
this.multimedia = multimedia;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(section);
dest.writeValue(subsection);
dest.writeValue(title);
dest.writeValue(_abstract);
dest.writeValue(url);
dest.writeValue(byline);
dest.writeValue(itemType);
dest.writeValue(updatedDate);
dest.writeValue(createdDate);
dest.writeValue(publishedDate);
dest.writeValue(materialTypeFacet);
dest.writeValue(kicker);
dest.writeList(desFacet);
dest.writeValue(orgFacet);
dest.writeValue(perFacet);
dest.writeList(geoFacet);
dest.writeList(multimedia);
}
public int describeContents() {
return 0;
}
}
答案 0 :(得分:1)
你还没有附加你的结果类,但它看起来像你的结果类有一个字符串字段而不是org_facet中的数组。但是,如果添加Result类,则更容易回答。
答案 1 :(得分:1)
自动POJO生成器在某些情况下可能会生成错误的映射,尤其是在映射字段是多态的情况下或出于任何原因使用非标准方法时。根据您获得的错误,您的映射需要String
,但JSON在该位置有一个数组。在您的情况下,$.results[0].org_facet
指向:
...,"org_facet":["Amazon.com Inc","Cravath Swaine \u0026 Moore"],...
// ^____here
如果您将地图String orgFacet
更改为List<String> orgFacet
,则会为perFacet
或multimedia
等其他字段带来类似错误(周围还有更多)。由于这些字段是列表而""
只是空数组[]
或null
的标记,因此Gson无法处理它,因为这种消息格式。但是,您可以使用此类字段编写自定义类型适配器,该适配器适用于使用单个Gson
实例反序列化的所有列表。
final class ArrayOrEmptyStringTypeAdapter<E>
extends TypeAdapter<List<E>> {
private final Gson gson;
private final Type elementType;
private ArrayOrEmptyStringTypeAdapter(final Gson gson, final Type elementType) {
this.gson = gson;
this.elementType = elementType;
}
static <E> TypeAdapter<List<E>> getArrayOrEmptyStringTypeAdapter(final Gson gson, final Type elementType) {
return new ArrayOrEmptyStringTypeAdapter<>(gson, elementType);
}
@Override
public void write(final JsonWriter out, final List<E> list) {
throw new UnsupportedOperationException();
}
@Override
public List<E> read(final JsonReader in)
throws IOException {
final JsonToken token = in.peek(); // Peek the next token
switch ( token ) {
case BEGIN_ARRAY: // If it's an array begin `[`, then parse it as an array
return parseAsArray(in);
case STRING: // Or if it's a string, parse it in another way
return parseAsString(in);
default:
throw new MalformedJsonException("Unexpected token: " + token);
}
}
private List<E> parseAsArray(final JsonReader in)
throws IOException {
final List<E> list = new ArrayList<>();
in.beginArray(); // Consume `[` from the token stream
while ( in.peek() != END_ARRAY ) {
final E element = gson.fromJson(in, elementType); // Delegate downstream parsing to the Gson instance
list.add(element);
}
in.endArray(); // Consume `]` from the token stream
return list;
}
private List<E> parseAsString(final JsonReader in)
throws IOException {
in.skipValue(); // in.nextString() consumes more memory accumulating the result
return new ArrayList<>(); // Or null -- up to you. Or even Collections.emptyList(), but Gson uses mutable lists so we do
}
}
接下来是通过类型适配器工厂绑定类型适配器和Gson
实例:
final class ArrayOrEmptyStringTypeAdapterFactory
implements TypeAdapterFactory {
private static final TypeAdapterFactory arrayOrEmptyStringTypeAdapterFactory = new ArrayOrEmptyStringTypeAdapterFactory();
private ArrayOrEmptyStringTypeAdapterFactory() {
}
static TypeAdapterFactory getArrayOrEmptyStringTypeAdapterFactory() {
return arrayOrEmptyStringTypeAdapterFactory;
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
if ( List.class.isAssignableFrom(typeToken.getRawType()) ) { // Is it an instance of java.util.List? Not that getRawType() and getType() have different purposes
final TypeAdapter<List<Object>> typeAdapter = getArrayOrEmptyStringTypeAdapter(gson, getListElementType(typeToken.getType()));
@SuppressWarnings("unchecked")
final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) typeAdapter;
return castTypeAdapter;
}
return null;
}
private static Type getListElementType(final Type type) {
return type instanceof ParameterizedType // Is it a generic type with type parameters?
? ((ParameterizedType) type).getActualTypeArguments()[0] // If yes, then we know that java.util.List has one type paremeter only
: Object.class; // Otherwise it's a raw list, and no element type info is provided
}
}
如何使用:
private static final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(getArrayOrEmptyStringTypeAdapterFactory())
.create();
final NewsEntities newEntities = gson.fromJson(jsonString, NewsEntities.class);
System.out.println(newEntities.results.get(0).orgFacet);
System.out.println(newEntities.results.get(0).perFacet)
输出:
[Amazon.com Inc,Cravath Swaine&amp;穆尔]
[Bezos,Jeffrey P]