我正在使用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
类之间使用多个关系,但作者没有保存到数据库,因为他们没有@Expose
注释Article
类中的(甚至是变量),并且没有办法使用该注释,因为有很多调用将是一个方法调用,返回List<Author>
。
// This will not work
@Expose
public List<Author> authors() {
return getMany(Author.class, "Article");
}
所以我想的另一种方法是将JSON对象作为字符串存储在数据库中,并序列化/反序列化以进行访问。
这要求我将authors
变量设为List<Author>
类,并为其提供type serializer。
这种方法的问题是我无法知道保存到数据库中的通用类型。我无法返回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数组视为String。
所以我的问题是如何使用GSON转换器将一些JSON数组视为字符串。
我正在使用的我的改造生成器是: -
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()));
谢谢你看看!
答案 0 :(得分:0)
你可以使用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())
答案 1 :(得分:0)
Blackbelt说,用于存储为String。
理智的方法是拥有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不支持这种关系需要junction table, as described in this issue on github
答案 2 :(得分:0)
一种可能的解决方案。
只需将字段声明为Object,然后Gson将其反序列化为 LinkedTreeMap
尝试将LinkedTreeMap转换为JsonObject,如下所示
LinkedTreeMap<?,?> yourMap = ...;
JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();
答案 3 :(得分:0)
使用自定义Map
覆盖标准操作。呼叫密钥Set
上的Map
JsonDeserializer<Article>
并注册自定义反序列化器
toString()
也不要忘记使用authors
批注或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;
}
}
答案 4 :(得分:0)
如果有人仍想将嵌套对象保留为字符串,则可以对应保留字符串的字段使用@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();
}
}