【问题标题】:Translating nested Java objects to/from json using gson使用 gson 将嵌套的 Java 对象与 json 进行转换
【发布时间】:2014-07-18 03:33:13
【问题描述】:

假设我们有以下两个 Java 类(省略其他类成员):

class Book {
    private String name;
    private String[] tags;
    private int price;
    private Author author;
}

class Author {
    private String name;
}

此外,假设我们有以下 json 对象:

{"Book": {
    "name": "Bible",
    "price": 20,
    "tags": ["God", "Religion"],
    "writer": {
        "name": "Jesus"
    }
}

我正在尝试找到将 Java Book 实例转换为 json 并使用 gson 转换回来的最佳方法。为了使示例更有趣,请注意在 json 中,我想使用“writer”而不是“Author”。你能帮忙吗?理想情况下,我希望看到一个完整的实现。

【问题讨论】:

  • 我们能看到你们在这方面的一些努力吗?
  • 理想情况下,我们不想做你的功课。如果你谷歌一下,你会发现很多关于如何使用 gson 的示例实现。
  • 在此处验证您的 JSON 字符串 JSONLint - The JSON Validator
  • 只有当我搜索答案失败时,我才会在此处发布。我已经熟悉 gson 以及如何手动将对象转换为 json 或从 json 转换,这对于大型 Java 对象来说是一项繁琐的任务。我主要是通过配置 gson 来自动完成这项工作(特别是对于 fromJson)。我在上面发布的示例是人为的,但它包含了我需要学习的所有内容,以便进行自己的编码。我的主要问题是关于配置 gson 以知道“writer”键的值应该转换为 Author 类的实例。我不知道该怎么做。

标签: java json gson


【解决方案1】:

感谢您的所有回答。我能够弄清楚它并使用一些自定义序列化器和反序列化器来实现它。这是我自己的解决方案:

public class JsonTranslator {
    private static Gson gson = null;

    public void test(Book book1) {
        JsonElement je = gson.toJson(book1);  // convert book1 to json
        Book book2 = gson.fromJson(je, Book.class); // convert json to book2
        // book1 and book2 should be equivalent
    }

    public JsonTranslator() {

        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(Book.class, new BookTrnaslator());
        builder.registerTypeAdapter(Author.class, new AuthorTrnaslator());
        builder.setPrettyPrinting();
        gson = builder.create();
    }


    private class BookTrnaslator implements JsonDeserializer<Book>, JsonSerializer<Book> {
        public Card deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject jobj = json.getAsJsonObject();
            Book book = new Book();
            book.setName(jobj.get("name").getAsString());
            book.setTags(jobj.get("tags").getAsJsonArray()); //Assuming setTags(JsonArray ja) exists
            book.setName(jobj.get("price").getAsInt());
            book.setAuthor(gson.fromJson(jobj.get("writer"), Author.class));
            return book;
        }

       public JsonElement serialize(Book src, Type typeOfSrc, JsonSerializationContext context) {
            JsonObject jobj = new JsonObject();
            jobj.addProperty("name", src.getName());
            jobj.add("tags", src.getTagsAsJsonArray());
            jobj.addProperty("price", src.getPrice());
            jobj.add("writer", gson.toJson(src.getAuthor()));
            return jobj;
       }
    }

    private class AuthorTrnaslator implements JsonDeserializer<Author>, JsonSerializer<Author> {
        public Card deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject jobj = json.getAsJsonObject();
            Author author = new Author();
            author.setName(jobj.get("name").getAsString());
            return author;
        }

       public JsonElement serialize(Author src, Type typeOfSrc, JsonSerializationContext context) {
            JsonObject jobj = new JsonObject();
            jobj.addProperty("name", src.getName());
            return jobj;
       }
    }
}

【讨论】:

    【解决方案2】:

    尝试使用 GsonBuilder#setPrettyPrinting() 配置 Gson 以输出适合页面以进行漂亮打印的 Json。此选项仅影响 Json 序列化。

    阅读更多关于 Gson 的信息,它通常通过首先构造一个 Gson 实例然后在其上调用以下方法来使用。


    BookDetails 对象到 JSON 字符串

    示例代码:

    Book book = new Book();
    book.setName("Bible");
    book.setTags(new String[] { "God", "Religion" });
    book.setPrice(20);
    Author author = new Author();
    author.setName("Jesus");
    book.setWriter(author);
    
    BookDetails bookDetails = new BookDetails();
    bookDetails.setBook(book);
    
    String jsonString = new Gson().toJson(bookDetails);
    // JOSN with pretty printing
    // String jsonString = new GsonBuilder().setPrettyPrinting().create().toJson(bookDetails);
    System.out.println(jsonString);
    

    输出:

    {"Book":{"name":"Bible","tags":["God","Religion"],"price":20,"writer":{"name":"Jesus"}}}
    

    JSON 字符串到 BookDetails 对象

    BookDetails newBookDetails = new Gson().fromJson(jsonString, BookDetails.class);
    

    这是课程

    class BookDetails {
        private Book Book;
        // getter & setter
    }
    
    class Book {
        private String name;
        private String[] tags;
        private int price;
        // Variable name should be writer instead of author as mapped to JSON string
        private Author writer; 
        // getter & setter
    }
    
    class Author {
        private String name;
        // getter & setter
    }
    

    【讨论】:

    • 谢谢。只有两个简单的问题:为什么需要实现 BookDetails?而且,如何告诉 gson 将 json 对象中“writer”的值映射到 Author 类的实例,反之亦然?
    • 所有 POJO 类都应具有与 JSON 字符串中所示相同的副本。变量名必须区分大小写。阅读Why does GSON use fields and not getters/setters?。在这里,您创建了一个变量writer,它的类型为Author,Gson 从字段中读取并将name 的值分配给Authorname 变量。这里BookDetails 的使用方式与variable 的使用方式相同,该variable 表示JSON 字符串的初始Book 值,并以与Author 相同的方式进行映射。
    • 让我总结一下 - Gson 使用 字段名称 将 JSON 字符串映射到对象,反之亦然。
    • 使用Author writer;而不是Author author;从JSON字符串映射writer
    • 如果问题得到解决,不要忘记关闭线程。您已经问了 7 个问题,但没有一个是关闭的?
    猜你喜欢
    • 2017-07-27
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多