使用Gson反序列化JSON时引用父对象

The*_*ech 3 java json gson deserialization

给出以下JSON:

{
    "authors": [{
        "name": "Stephen King",
        "books": [{
            "title": "Carrie"
        }, {
            "title": "The Shining"
        }, {
            "title": "Christine"
        }, {
            "title": "Pet Sematary"
        }]
    }]
}
Run Code Online (Sandbox Code Playgroud)

而这个对象结构:

public class Author {
    private List<Book> books;
    private String name;
}

public class Book {
    private transient Author author;
    private String title;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法,使用谷歌Java库Gson,反序列化JSON,书籍对象有引用"父"作者对象?

是否可以使用自定义解串器?

  • 如果是的话:怎么样?
  • 如果否:是否仍然可以使用自定义反序列化程序执行此操作?

nic*_*ckb 6

在这种情况下,我将JsonDeserializer为父对象实现一个自定义,并传播Author信息,如下所示:

public class AuthorDeserializer implements JsonDeserializer<Author> {
    @Override
    public Author deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        final JsonObject authorObject = json.getAsJsonObject();

        Author author = new Author();
        author.name = authorObject.get("name").getAsString();

        Type booksListType = new TypeToken<List<Book>>(){}.getType();
        author.books = context.deserialize(authorObject.get("books"), booksListType);

        for(Book book : author.books) {
            book.author = author;
        }

        return author;
    }   
}
Run Code Online (Sandbox Code Playgroud)

请注意,我的示例省略了错误检查.你会像这样使用它:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Author.class, new AuthorDeserializer())
    .create();
Run Code Online (Sandbox Code Playgroud)

为了显示它的工作原理,我从你的示例JSON中删除了"authors"键,允许我这样做:

JsonElement authorsJson  = new JsonParser().parse(json).getAsJsonObject().get("authors");

Type authorList = new TypeToken<List<Author>>(){}.getType();
List<Author> authors = gson.fromJson(authorsJson, authorList);
for(Author a : authors) {
    System.out.println(a.name);
    for(Book b : a.books) {
        System.out.println("\t " + b.title + " by " + b.author.name);
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个印刷:

Stephen King
     Carrie by Stephen King
     The Shining by Stephen King
     Christine by Stephen King
     Pet Sematary by Stephen King
Run Code Online (Sandbox Code Playgroud)

  • @Thermech - 我不确定GSON能解决这个问题.您的另一个选择是执行默认反序列化,然后对结果进行后处理.你*可以*为`Author`创建一个构造函数,它接受一个`JsonObject`并使用它来填充原始字段,将该逻辑保持在`Author`类中.类似地,您可以创建一个构造函数,将所有基本类型作为参数,这会强制您在对类进行更改时更新反序列化程序. (2认同)