2017-02-25 63 views
0

由于某些原因,我无法将其转换为POJO。我正在做的尝试是这样的:由于错误,无法将json字符串转换为POJO预期字符串,但是BEGIN_ARRAY

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; 
    } 

} 

回答

1

在某些情况下,自动POJO生成器可能会生成错误的映射,特别是如果映射字段是多态的或者出于任何原因使用非标准方法。根据你得到的错误,你的映射需要一个String,但JSON在那个地方有一个数组。在你的情况,$.results[0].org_facet点:

...,"org_facet":["Amazon.com Inc","Cravath Swaine \u0026 Moore"],... 
      // ^____here 

如果改变映射String orgFacetList<String> orgFacet,你会得到像perFacetmultimedia另一场类似的错误(也有一些更多的周围)。由于这些字段是列表,""只是空数组[]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公司,克雷弗斯施伟贤&摩尔]
[贝索斯,杰弗里·P]

1

你还没有附加你的结果类,但它在我看来像你的结果类有一个字符串字段,而不是org_facet中的数组。但如果添加Result类,它会更容易回答。

+0

我张贴的结果类为您诊断。 – j2emanue