我正在尝试使用类似数据库的GSON构建。我想存储相同对象的记录,并且能够随时附加新记录。此外,我正在尝试构建解析器,它将从json到ArrayList的所有对象。我怎么能这样做?目前我写了这样的东西:
public void addRecord(Record record) throws IOException {
JsonWriter writer = new JsonWriter(new FileWriter("/file.json", true));
writer.setIndent(" ");
gson.toJson(record, Record.class, writer);
writer.close();
}
但是,intelliJ告诉我,JSON标准只允许一个顶级值。怎么避免呢?据我所知,文件应该只包含一个列表,我应该添加新的对象,但我不知道如何。另外,如何将它们解析为ArrayList?
答案 0 :(得分:1)
但是,intelliJ告诉我,JSON标准只允许一个顶级值。
是。 您实现的是串联JSON(请参阅more)。 您仍然可以使用它,但您的记录文件不会被符合JSON标准的工具解析。 如果你不想使用" raw" JSON流,您可以实现基于JSON数组的流。 这需要一些工作,但它可以让你生成和使用有效的JSON文档。
final class JsonStreams {
private JsonStreams() {
}
@SuppressWarnings("resource")
static void copy(final JsonReader reader, final JsonWriter writer)
throws IOException {
int level = 0;
loop:
for ( JsonToken token = reader.peek(); token != null; token = reader.peek() ) {
switch ( token ) {
case BEGIN_ARRAY:
reader.beginArray();
writer.beginArray();
++level;
break;
case END_ARRAY:
reader.endArray();
writer.endArray();
if ( --level == 0 ) {
return;
}
break;
case BEGIN_OBJECT:
reader.beginObject();
writer.beginObject();
++level;
break;
case END_OBJECT:
reader.endObject();
writer.endObject();
if ( --level == 0 ) {
return;
}
break;
case NAME:
final String name = reader.nextName();
writer.name(name);
break;
case STRING:
final String s = reader.nextString();
writer.value(s);
break;
case NUMBER:
final Number n = new BigDecimal(reader.nextString());
writer.value(n);
break;
case BOOLEAN:
final boolean b = reader.nextBoolean();
writer.value(b);
break;
case NULL:
reader.nextNull();
writer.nullValue();
break;
case END_DOCUMENT:
break loop;
default:
throw new AssertionError(token);
}
}
}
static void appendToArray(final JsonReader jsonReader, final JsonWriter jsonWriter, final Consumer<? super JsonWriter> consumer)
throws IOException {
// Making JsonReader set to END_DOCUMENT if there is a blank/whitespace document
try {
jsonReader.hasNext();
} catch ( final EOFException ignored ) {
}
// Checking the outer-most JSON token
final JsonToken beginJsonToken = jsonReader.peek();
switch ( beginJsonToken ) {
// If it's a blank/whitespace document, then just write a single row
case END_DOCUMENT:
jsonWriter.beginArray();
consumer.accept(jsonWriter);
jsonWriter.endArray();
break;
// If the document starts with [, then unroll all its values
case BEGIN_ARRAY:
jsonReader.beginArray();
jsonWriter.beginArray();
final JsonToken endJsonToken = jsonReader.peek();
if ( endJsonToken != JsonToken.END_ARRAY ) {
// Copy all existing values
while ( jsonReader.hasNext() ) {
final JsonToken rowJsonToken = jsonReader.peek();
switch ( rowJsonToken ) {
case BEGIN_ARRAY:
case BEGIN_OBJECT:
case STRING:
case NUMBER:
case BOOLEAN:
case NULL:
copy(jsonReader, jsonWriter);
break;
// The rest of tokens must never happen because we copy values
case END_ARRAY:
case END_OBJECT:
case NAME:
case END_DOCUMENT:
default:
throw new AssertionError(rowJsonToken);
}
}
}
consumer.accept(jsonWriter);
// End the document with ]
jsonReader.endArray();
jsonWriter.endArray();
break;
default:
throw new JsonParseException("Unexpected outer token: " + beginJsonToken);
}
}
}
public static void main(final String... args)
throws IOException {
final Iterable<String> resourceNames = ImmutableList.of("1-blank.json", "2-empty.json", "3-some.json");
for ( final String resourceName : resourceNames ) {
try ( final JsonReader jsonReader = Resources.getPackageResourceJsonReader(Q50418170.class, resourceName) ) {
final Writer writer = new StringWriter();
final JsonWriter jsonWriter = new JsonWriter(writer);
JsonStreams.appendToArray(jsonReader, jsonWriter, jw -> {
gson.toJson(fooBar(1, 2), jw);
gson.toJson(fooBar(3, 4), jw);
gson.toJson(fooBar(5, 6), jw);
});
System.out.println(writer);
}
}
}
private static JsonElement fooBar(final int foo, final int bar) {
final JsonObject jsonObject = new JsonObject();
jsonObject.add("foo", new JsonPrimitive(foo));
jsonObject.add("bar", new JsonPrimitive(bar));
return jsonObject;
}
以上测试文件如下:
&lt; no content;零长度文件&gt;
[
]
本文档按意图格式化,但我会将JSON文档存档缩小(因此,我不会使用setIndent
)。
[
{
"foo": 0,
"bar": 0,
"baz": [
1,
2,
3
]
}
]
上述文件的测试将产生以下输出
[{"foo":1,"bar":2},{"foo":3,"bar":4},{"foo":5,"bar":6}]
[{"foo":1,"bar":2},{"foo":3,"bar":4},{"foo":5,"bar":6}]
[{"foo":0,"bar":0,"baz":[1,2,3]},{"foo":1,"bar":2},{"foo":3,"bar":4},{"foo":5,"bar":6}]