我想用字符串数组创建一个 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/