I am using a ActiveAndroid to cache response from Retrofit network calls.
我正在使用ActiveAndroid缓存来自Retrofit网络调用的响应。
I made a class which looks like :-
我做了一个看起来像这样的课:
class Article extends Model {
@Column(name = "title")
@SerializedName("title")
@Expose
public String title;
@Column(name = "authors")
@SerializedName("authors")
@Expose
private String authors;
}
The corresponding JSON is something like :-
相应的JSON类似于: -
{
"title":"Some title",
"authors": [{
"name": "Name",
"twitter":"@whatever"
}]
}
The sane way would be to use a has many relationship between Author
and Article
class, but authors are not being saved to database because they don't have @Expose
annotation (or even a variable) in the Article
class, and there is no way to have that annotation because has many calls will be a method call here which returns a List<Author>
.
理智的方法是使用Author和Article类之间有很多关系,但是作者没有被保存到数据库,因为他们在Article类中没有@Expose注释(甚至是变量),也没办法有这个注释因为有很多调用将是一个方法调用这里返回一个List
// This will not work
@Expose
public List<Author> authors() {
return getMany(Author.class, "Article");
}
So the other way I thought was to store the JSON object in database as a string and serialize/deserialize for access.
所以我想的另一种方式是将JSON对象作为字符串存储在数据库中,并进行序列化/反序列化以进行访问。
That requires me to have the authors
variable a List<Author>
class, and provide a type serializer for it.
这要求我让作者变量为List
The problem with this approach is I have no way of knowing the Generic type being saved into the database. I can't return a List<Author>
type because just like authors, there are some more JSON Arrays in the whole of JSON.
这种方法的问题是我无法知道保存到数据库中的泛型类型。我无法返回List
So my the final solution that I have thought of is to store it as a string, treat it as a string and make a method to deserialize for access. Like this :-
所以我想到的最终解决方案是将其存储为字符串,将其视为字符串并制作反序列化访问方法。喜欢这个 :-
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;
}
But when I try to do this, GSON throws an error :-
但是当我尝试这样做时,GSON会抛出一个错误: -
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY
com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:期望一个字符串,但是是BEGIN_ARRAY
Basically saying that I am trying to treat a JSON array as a String.
基本上说我试图将JSON数组视为String。
So my question is how to treat some of the JSON Arrays as Strings with GSON converters.
所以我的问题是如何使用GSON转换器将一些JSON数组视为字符串。
My Retrofit Builder which I am using is :-
我正在使用的改造生成器是: -
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()));
Thanks for taking a look!
谢谢参观!
3 个解决方案
#1
0
you could use a JsonDeserializer for it, registered on Article
您可以在文章中注册使用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;
}
and you will have to register it to gson
你必须将它注册到gson
gsonBuilder.registerTypeHierarchyAdapter(Article.class, new ArticleDeseriazer())
#2
0
What Blackbelt said, for storing as String.
Blackbelt说,用于存储为String。
The sane way to do it would be to have a Author
class and then a 1:n. As far as I understand, writing releationship data is manual, so you have to save the relationship yourself when you save the Article
. So assuming you have the Author
class
理解它的方法是拥有一个Author类,然后是1:n。据我所知,编写关联数据是手动的,因此您必须在保存文章时自己保存关系。所以假设你有Author类
@Table(name = "Authors")
public class Author extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Twitter")
public String twitter;
}
and the field
和田野
private List<Author> authors;
in the Article
class, you would save the authors like this
在Article类中,您可以像这样保存作者
article.save();
for (author: Author in arcticle.authors) {
author.article = article;
author.save();
}
and then you could add the method for accessing an Article
's authors as documented:
然后你可以添加访问文章作者的方法,如下所示:
public List<Author> getAuthors() {
return getMany(Author.class, "Author");
}
So GSON stores the authors in the field authors, when saving the Authors get insterted to their own table, and getAuthors()
reads them from the database.
因此,当将作者保存在他们自己的表中时,GSON将作者存储在字段作者中,并且getAuthors()从数据库中读取它们。
note: m:n probably makes more sense as a relationship between Article
and Author
, which is not supported by ActiveAndroid and needs a junction table, as described in this issue on github
注意:m:n可能更有意义作为文章和作者之间的关系,ActiveAndroid不支持并且需要联结表,如本期github中所述
#3
0
one possible solution.
一种可能的解决方
-
Just declare field as Object, then Gson will deserialize it as LinkedTreeMap
只需将字段声明为Object,然后Gson将其反序列化为LinkedTreeMap
-
Try convert LinkedTreeMap to JsonObject as below
尝试将LinkedTreeMap转换为JsonObject,如下所示
LinkedTreeMap<?,?> yourMap = ...; JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();
LinkedTreeMap <?,?> yourMap = ...; JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();
#1
0
you could use a JsonDeserializer for it, registered on Article
您可以在文章中注册使用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;
}
and you will have to register it to gson
你必须将它注册到gson
gsonBuilder.registerTypeHierarchyAdapter(Article.class, new ArticleDeseriazer())
#2
0
What Blackbelt said, for storing as String.
Blackbelt说,用于存储为String。
The sane way to do it would be to have a Author
class and then a 1:n. As far as I understand, writing releationship data is manual, so you have to save the relationship yourself when you save the Article
. So assuming you have the Author
class
理解它的方法是拥有一个Author类,然后是1:n。据我所知,编写关联数据是手动的,因此您必须在保存文章时自己保存关系。所以假设你有Author类
@Table(name = "Authors")
public class Author extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Twitter")
public String twitter;
}
and the field
和田野
private List<Author> authors;
in the Article
class, you would save the authors like this
在Article类中,您可以像这样保存作者
article.save();
for (author: Author in arcticle.authors) {
author.article = article;
author.save();
}
and then you could add the method for accessing an Article
's authors as documented:
然后你可以添加访问文章作者的方法,如下所示:
public List<Author> getAuthors() {
return getMany(Author.class, "Author");
}
So GSON stores the authors in the field authors, when saving the Authors get insterted to their own table, and getAuthors()
reads them from the database.
因此,当将作者保存在他们自己的表中时,GSON将作者存储在字段作者中,并且getAuthors()从数据库中读取它们。
note: m:n probably makes more sense as a relationship between Article
and Author
, which is not supported by ActiveAndroid and needs a junction table, as described in this issue on github
注意:m:n可能更有意义作为文章和作者之间的关系,ActiveAndroid不支持并且需要联结表,如本期github中所述
#3
0
one possible solution.
一种可能的解决方
-
Just declare field as Object, then Gson will deserialize it as LinkedTreeMap
只需将字段声明为Object,然后Gson将其反序列化为LinkedTreeMap
-
Try convert LinkedTreeMap to JsonObject as below
尝试将LinkedTreeMap转换为JsonObject,如下所示
LinkedTreeMap<?,?> yourMap = ...; JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();
LinkedTreeMap <?,?> yourMap = ...; JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();