如何使用Gson,Retrofit,Active Android将嵌套的JSON对象反序列化为String

时间:2022-09-10 13:37:50

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 类型,因为就像作者一样,整个JSON中还有一些JSON数组。

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.

一种可能的解决方

  1. Just declare field as Object, then Gson will deserialize it as LinkedTreeMap

    只需将字段声明为Object,然后Gson将其反序列化为LinkedTreeMap

  2. 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.

一种可能的解决方

  1. Just declare field as Object, then Gson will deserialize it as LinkedTreeMap

    只需将字段声明为Object,然后Gson将其反序列化为LinkedTreeMap

  2. 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();