2017-02-12 3 views
0

Я использую ActiveAndroid для ответа на кеш от сетевых перенастроек.Как десериализовать вложенный объект JSON как String с помощью Gson, Retrofit, Active Android

Я сделал класс, который выглядит следующим образом: -

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.

Проблема с этим подходом заключается в том, что я не могу знать, что тип 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 в виде строки.

Итак, мой вопрос заключается в том, как обрабатывать некоторые из массивов JSON как строки с преобразователями GSON.

My дооснащения 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())); 

Спасибо за взглянуть!

+0

что вы имеете в виду * и нет никакой возможности иметь эту аннотацию, потому что здесь много вызовов будет вызовом метода, который возвращает Список *? – Blackbelt

+0

@Blackbelt обновил мой вопрос, чтобы объяснить это. – Shobhit

+0

Я еще не совсем уверен, что вы имеете в виду. Почему статья не может содержать личный список авторов; '? – Blackbelt

ответ

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()) 
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 классе, вы save the authors like this

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

0

одно из возможных решений.

  1. Просто объявить поле как объект, то Gson будет десериализации как LinkedTreeMap

  2. Попробуйте преобразовать LinkedTreeMap в JSONObject ниже

    LinkedTreeMap<?,?> yourMap = ...; JsonObject jsonObject = gson.toJsonTree(yourMap).getAsJsonObject();

Смежные вопросы