![](/img/trans.png)
[英]How do I parse a field from a deep nested json object using Gson and retrofit in android?
[英]How to deserialize a nested JSON object as a String with Gson, Retrofit, Active Android
我正在使用 ActiveAndroid 來緩存來自 Retrofit 網絡調用的響應。
我做了一個看起來像的課程:-
class Article extends Model {
@Column(name = "title")
@SerializedName("title")
@Expose
public String title;
@Column(name = "authors")
@SerializedName("authors")
@Expose
private String authors;
}
相應的 JSON 類似於:-
{
"title":"Some title",
"authors": [{
"name": "Name",
"twitter":"@whatever"
}]
}
明智的方法是在Author
和Article
類之間使用有很多關系,但是作者沒有被保存到數據庫中,因為他們在Article
類中沒有@Expose
注釋(甚至變量),並且沒有辦法擁有該注釋,因為有很多調用將是一個返回List<Author>
的方法調用。
// This will not work
@Expose
public List<Author> authors() {
return getMany(Author.class, "Article");
}
所以我認為的另一種方法是將 JSON 對象作為字符串存儲在數據庫中並序列化/反序列化以供訪問。
這要求我讓authors
變量成為List<Author>
類,並為其提供 類型序列化程序。
這種方法的問題是我無法知道正在保存到數據庫中的 Generic 類型。 我不能返回List<Author>
類型,因為就像作者一樣,在整個 JSON 中有更多的 JSON 數組。
所以我想到的最終解決方案是將其存儲為字符串,將其視為字符串並制作一種反序列化以供訪問的方法。 像這樣 :-
private List<Author> _authors;
public List<Author> authors() {
if (_authors == null) {
Gson gson = ServiceGenerator.gsonBuilder.create();
Type type = new TypeToken<List<Author>>(){}.getType();
_authors = gson.fromJson(authors, type);
}
return _authors;
}
但是當我嘗試這樣做時,GSON 會拋出一個錯誤:-
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY
基本上是說我試圖將 JSON 數組視為字符串。
所以我的問題是如何使用 GSON 轉換器將一些 JSON 數組視為字符串。
我正在使用的 Retrofit Builder 是:-
public static final GsonBuilder gsonBuilder = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.excludeFieldsWithoutExposeAnnotation();
private static final Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()));
謝謝參觀!
如果有人仍然想將嵌套對象保留為字符串,那么您可以對應該保留字符串的字段使用 @JsonAdapter 注釋。
@JsonAdapter(RawStringTypeAdapter.class)
private String Authors;
和 RawStringTypeAdapter:
public final class RawStringTypeAdapter<T>
implements JsonDeserializer<T> {
private RawStringTypeAdapter() {
}
@Override
public T deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context)
throws JsonParseException {
return (T) jsonElement.toString();
}
}
你可以使用 JsonDeserializer,在文章中注冊
public class ArticleDeserializer implements JsonDeserializer<Article> {
@Override
public Article deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
Article article = context.deserialize(json, Article.class);
JsonArray authors = json.getAsJsonObject().getAsJsonArray("authors");
// convert authors as string and set it to artile
return article;
}
你必須將它注冊到 gson
gsonBuilder.registerTypeHierarchyAdapter(Article.class, new ArticleDeseriazer())
Blackbelt 所說的,用於存儲為字符串。
明智的做法是先創建一個Author
類,然后再創建一個 1:n。 據我了解,編寫關系數據是手動的,所以你在保存Article
時必須自己保存關系。 所以假設你有Author
類
@Table(name = "Authors")
public class Author extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Twitter")
public String twitter;
}
和領域
private List<Author> authors;
在Article
類中,你會像這樣保存作者
article.save();
for (author: Author in arcticle.authors) {
author.article = article;
author.save();
}
然后您可以添加用於訪問Article
的作者的方法,如文檔所示:
public List<Author> getAuthors() {
return getMany(Author.class, "Author");
}
因此,GSON 將作者存儲在字段作者中,保存作者時會插入到他們自己的表中,並且getAuthors()
從數據庫中讀取它們。
注意: m:n 作為Article
和Author
之間的關系可能更有意義,ActiveAndroid 不支持這種關系並且需要一個連接表,如 github 上的這個問題中所述
一種可能的解決方案。
只需將字段聲明為 Object,然后 Gson 會將其反序列化為LinkedTreeMap
嘗試將 LinkedTreeMap 轉換為 JsonObject,如下所示
LinkedTreeMap<?,?> yourMap = ...; JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();
使用自定義JsonDeserializer<Article>
覆蓋標准操作。 對關鍵authors
調用toString()
public class CustomDeserializer implements JsonDeserializer<Article> {
@Override
public Article deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if(json.isJsonObject()) {
JsonObject jsonObj = json.getAsJsonObject();
Article item = context.deserialize(json, Article.class);
if(jsonObj.has("authors")) {
item.setAuthors(jsonObj.get("authors").toString());
}
return item;
}
return null;
}
}
並注冊自定義解串器
Gson gson = new GsonBuilder().registerTypeAdapter(Article.class, new CustomDeserializer()).create();
並且不要忘記使用@Expose
注釋或addDeserializationExclusionStrategy()
從 gson 反序列化中排除關鍵作者
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.