java - 创建动态嵌套 JSON Java

标签 java json rest gson

我想用字符串数组创建一个 Json,每个字符串看起来像: “id.categoryvalue.subcatvalue.subsubcatvalue.score” 结果应如下所示:

{
  "user-id": "u42",
  "categories": [
    {
      "category": "value",
      "subcats": [
        {
          "subcat": "value",
          "subsubcats": [
            {
              "subsubcat": "value",
              "score": 47
            }  
          ]
        }
      ]
    }
  ]
}

我不想在同一类别中重复一个值,什么是有效的解决方法?谢谢!

最佳答案

使用 Gson,您可以使用对象模型方式或流式传输方式生成 JSON。第一个要求在生成 JSON 之前以强类型方式(见下文)或弱类型方式构建整个对象(就像 Darshan Mehta 建议的那样——他使用了基于 Java 映射的弱对象)。

对象模型方法

将给定的数据分解为多个数据包类,构造这些类的对象,然后调用Gson:

public final class ObjectModelDemo {

    private ObjectModelDemo() {
    }

    public static void main(final String... args) {
        final String[] tokens = "id31.english.B1.Animals.11".split("\\.");
        if ( tokens.length != 5 ) {
            throw new IllegalArgumentException("Not 5 tokens in " + "id31.english.B1.Animals.11");
        }
        final String userId = tokens[0];
        final String category = tokens[1];
        final String subcategory = tokens[2];
        final String subsubcategory = tokens[3];
        final int score = parseInt(tokens[4]);
        final User user = new User(
                userId,
                singletonList(new Category(
                        category,
                        singletonList(new Subcategory(
                                subcategory,
                                singletonList(new Subsubcategory(subsubcategory, score))
                        ))
                ))
        );
        final Gson gson = new GsonBuilder().create();
        out.println(gson.toJson(user));
    }

    private static final class User {

        @SerializedName("user-id")
        private final String userId;

        @SerializedName("categories")
        private final List<Category> categories;

        private User(final String userId, final List<Category> categories) {
            this.userId = userId;
            this.categories = categories;
        }

    }

    private static final class Category {

        @SerializedName("category")
        private final String category;

        @SerializedName("subcats")
        private final List<Subcategory> subcategories;

        private Category(final String category, final List<Subcategory> subcategories) {
            this.category = category;
            this.subcategories = subcategories;
        }

    }

    private static final class Subcategory {

        @SerializedName("subcat")
        private final String subcategory;

        @SerializedName("subsubcats")
        private final List<Subsubcategory> subsubcategories;

        private Subcategory(final String subcategory, final List<Subsubcategory> subsubcategories) {
            this.subcategory = subcategory;
            this.subsubcategories = subsubcategories;
        }

    }

    private static final class Subsubcategory {

        @SerializedName("subsubcat")
        private final String subsubcategory;

        @SerializedName("score")
        private final int score;

        private Subsubcategory(final String subsubcategory, final int score) {
            this.subsubcategory = subsubcategory;
            this.score = score;
        }

    }

}

此类数据包称为 DTO ( data-transfer objects ),旨在在 Java 对象及其各自的 JSON 表示之间进行映射。这为 Java 编译器提供了非常强大的编译时控制支持。这种方法的缺点是您必须在任何 JSON 生成开始之前收集所有数据(通常这对于内存敏感的应用程序非常重要)。但是,对于您的情况,这可能要容易得多,而且可能是最简单的。

输出:

{"user-id":"id31","categories":[{"category":"english","subcats":[{"subcat":"B1","subsubcats":[{"subsubcat":"Animals","score":11}]}]}]}

流式传输方法

基于中间将 JSON 写入目标的替代方法。这种方法是一种更复杂的数据推送方法,但是从内存消耗的角度来看它更有效(更重要的是,您可以使用这种方法轻松生成无限的 JSON,但我怀疑您是否会遇到这种情况:))。

    public static void main(final String... args)
            throws IOException {
        final String[] tokens = "id21.english.B2.Insects.24".split("\\.");
        if ( tokens.length != 5 ) {
            throw new IllegalArgumentException("Not 5 tokens in " + "id21.english.B2.Insects.24");
        }
        final String userId = tokens[0];
        final String category = tokens[1];
        final String subcategory = tokens[2];
        final String subsubcategory = tokens[3];
        final int score = parseInt(tokens[4]);
        final JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(out));
        writeUser(jsonWriter, userId, category, subcategory, subsubcategory, score);
        jsonWriter.flush();
        // do not invoke jsonWriter.close() -- let the caller decide what to do
    }

    private static void writeUser(final JsonWriter jsonWriter, final String userId, final String category, final String subcategory,
            final String subsubcategory, final int score)
            throws IOException {
        jsonWriter.beginObject();
        jsonWriter.name("user-id");
        jsonWriter.value(userId);
        jsonWriter.name("categories");
        writeCategories(jsonWriter, category, subcategory, subsubcategory, score);
        jsonWriter.endObject();
    }

    private static void writeCategories(final JsonWriter jsonWriter, final String category, final String subcategory, final String subsubcategory,
            final int score)
            throws IOException {
        jsonWriter.beginArray();
        jsonWriter.beginObject();
        jsonWriter.name("category");
        jsonWriter.value(category);
        jsonWriter.name("subcats");
        writeSubcategories(jsonWriter, subcategory, subsubcategory, score);
        jsonWriter.endObject();
        jsonWriter.endArray();
    }

    private static void writeSubcategories(final JsonWriter jsonWriter, final String subcategory, final String subsubcategory, final int score)
            throws IOException {
        jsonWriter.beginArray();
        jsonWriter.beginObject();
        jsonWriter.name("subcat");
        jsonWriter.value(subcategory);
        jsonWriter.name("subsubcats");
        writeSubsubcategories(jsonWriter, subsubcategory, score);
        jsonWriter.endObject();
        jsonWriter.endArray();
    }

    private static void writeSubsubcategories(final JsonWriter jsonWriter, final String subsubcategory, final int score)
            throws IOException {
        jsonWriter.beginArray();
        jsonWriter.beginObject();
        jsonWriter.name("subsubcat");
        jsonWriter.value(subsubcategory);
        jsonWriter.name("score");
        jsonWriter.value(score);
        jsonWriter.endObject();
        jsonWriter.endArray();
    }

}

注意数据如何写入输出流:一旦您有足够的已知数据,您可以轻松地将其刷新到输出流。是的,这是一种更难编写的方法,但这是一种替代方法。

输出:

{"user-id":"id21","categories":[{"category":"english","subcats":[{"subcat":"B2","subsubcats":[{"subsubcat":"Insects","score":24}]}]}]}

关于java - 创建动态嵌套 JSON Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41535758/

相关文章:

java - 在java中创建多个线程

java - jetty、servlet 3.0、spring主机头攻击预防

php - MySQL表组织进行多维分类

ruby-on-rails - Rails 更新操作的路由助手是什么?

javascript - REST API 创建一个或多个资源?

java - 将模板应用到现有 HTML 代码的简单方法

java - 如何让 Spring JPA、Hibernate 和 OSGi 发挥出色?

javascript - MVC Controller 从具有数据的 JavaScript 对象传入 null

php - MDM DeviceLock 负载错误

javascript - 在 Post API 调用正文中动态传递参数