我試圖用Java和GSON來決議Musicbrainz.org的JSON格式的大型(約10GB)資料庫轉儲
。該JSON檔案有這樣的結構。沒有'[' ']'來表示這將是一個物件的陣列,而且每個物件之間沒有','。不知道為什么,但這個JSON檔案就是這樣的。
{
"id"。"d0ab06e1-751a-414b-a976-da72670391b1",
"name": "Arcing Wires",
"sort-name": "Arcing Wires", "sort-name".
}
{
"id": "6f0c2c16-dd7e-4268-a484-bc7b2ac78108",
"name": "另一個"。
"sort-name": "Another", "sort-name".
}
{
"id": "e062b6cd-5506-47b0-afdb-72f4279ec38c",
"name": "Agent S",
"sort-name": "Agent S", "sort-name".
}
而這是我正在使用的代碼:
。 try(JsonReader jsonReader = new JsonReader(
new InputStreamReader(
new FileInputStream(jsonFilePath), StandardCharsets.UTF_8))) {
Gson gson = new GsonBuilder() 。
jsonReader.beginArray()。
while (jsonReader.hasNext() ) {
Artist mapped = gson.fromJson(jsonReader, Artist.class)。
//TODO對該物件做一些處理。
}
}
jsonReader.endArray()。
}
catch (UnsupportedEncodingException e) {
e.printStackTrace()。
} catch(FileNotFoundException e) {
e.printStackTrace()。
} catch (IOException e) {
e.printStackTrace()。
}
而我所映射的類是這樣的:
public class Artist {
public String id;
public String name;
public String sortName;
}
我所得到的錯誤:
執行緒"main"中出現例外,java.lang.IllegalStateException。在1列2路徑$時,預期是BEGIN_ARRAY,但卻是BEGIN_OBJECT。
at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
at DBLoader.parse(DBLoader.java:39)
at DBLoader.main(DBLoader.java:23)
我相信GSON期望的結構與我宣告的不同,但我不明白我應該如何定義這種沒有逗號和括號的JSON。 有什么線索嗎? 謝謝
。uj5u.com熱心網友回復:
JSON默認只宣告一個頂層值(是的,這將是一個有效的JSON檔案),但有JSON流使用任意技術將多個JSON元素串聯成一個流,假設流消費者可以決議它(閱讀更多)。Gson支持一種所謂的寬松模式,它關閉了JsonReader的 "只有一個頂值 "模式(并做了一些與問題無關的事情)。setLenient。打開寬松模式后,你可以一個一個地讀取JSON元素,事實證明,這種模式可以用來決議/讀取以行為單位的JSON和concatenated JSON值,因為它們只是由Gson忽略的0個或多個空白點來劃分(因此更奇特的以記錄分隔符為單位的JSON和長度限定的JSON是不支持的)。它不能為你作業的原因是,你的初始代碼假定流包含一個單一的 JSON 陣列(而它顯然不是:它應該是一個不符合 JSON 陣列語法的元素流)。
一個簡單的通用 JSON 流支持可能看起來像這樣(使用 Stream API 的 API 比 Iterator 的 API 更豐富,但它可以展示一個想法,你可以很容易地將其調整為迭代器、回呼、可觀察的流,任何你喜歡的):
@UtilityClass
public final class JsonStreamSupport {
public static <T> Stream<T> parse(@WillNotClose final JsonReader jsonReader, final Function< ? super JsonReader, ? extends T> readElement) {
final boolean isLenient = jsonReader.isLenient()。
jsonReader.setLenient(true)。
final Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<T> (Long.MAX_VALUE, Spliterator.ORDERED) {
@Override.
public boolean tryAdvance(final Consumer<? super T> action) {
try {
final JsonToken token = jsonReader.peek()。
if ( token == JsonToken.END_DOCUMENT ) {
return false;
}
// TODO:在批處理中讀取更多的元素。
final T element = readElement.apply(jsonReader)。
action.accept(element)。
return true。
} catch ( final IOException ex ) {
throw new RuntimeException(ex)。
}
}
};
return StreamSupport.stream(spliterator, false)
.onClose(() -> jsonReader.setLenient(isLenient))。
}
}
然后:
JsonStreamSupport.<Artist>parse(jsonReader, jr -> gson.fromJson(jr, Artist.class) )
.forEach(System.out::println)。
輸出(假設Artist有Lombok生成的toString()):
藝術家(id=d0ab06e1-751a-414b-a976-da72670391b1, name=Arcing Wires, sortName=Arcing Wires)
Artist(id=6f0c2c16-dd7e-4268-a484-bc7b2ac78108, name=Another, sortName=Another)
藝術家(id=e062b6cd-5506-47b0-afdb-72f4279ec38c, name=Agent S, sortName=Agent S)
這樣的方法,JSON流,可以節省多少位元組,以便在你要消費的服務中使用?我不知道。
uj5u.com熱心網友回復:
它看起來像jsonl格式,每一行都是一個有效的JSON物件。(閱讀更多這里)
你可以逐行讀取檔案并轉換為物件。我想這是可行的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/334296.html
標籤:
