簡體   English   中英

如何用 Java 或 Kotlin 解析大型 YAML 文件?

[英]How to parse large YAML file in Java or Kotlin?

我有一個很大的 YAML 文件(~5MB),我需要使用 Kotlin/JVM 解析它。

我嘗試使用 Jackson 2.14.1 的流式 API,但它拋出:

com.fasterxml.jackson.dataformat.yaml.JacksonYAMLParseException: The incoming YAML document exceeds the limit: 3145728 code points.
 at [Source: (ZipInputStream); line: 122415, column: 9]
...
Caused by: org.yaml.snakeyaml.error.YAMLException: The incoming YAML document exceeds the limit: 3145728 code points.

我的 YAML 文件是一個包含大約 5k 個鍵的大字典,每個鍵都關聯了一個小文檔。 我流式傳輸根鍵並使用JsonParser.readValueAs()方法解析每個關聯的文檔。 因為我是流媒體,所以我希望字典的大小不會有問題,只要每個子文檔足夠小。 但是,有。 我在第 122415 行檢查了無法解析的文檔,它既不大(1.5KB)也不格式錯誤(根據https://www.yamllint.com/ )。

我的代碼是:

@Service
class Parser(
    @Qualifier("yamlMapper") private val yamlMapper: ObjectMapper,
) {
    fun parse(input: InputStream): Flow<Item> = flow {
        val parser = yamlMapper.factory.createParser(input)
        parser.use {
            parser.requireToken(JsonToken.START_OBJECT)
            var token = parser.nextToken()
            while (token != JsonToken.END_OBJECT) {
                if (token != JsonToken.FIELD_NAME) {
                    throw JsonParseException(parser, "Expected FIELD_NAME but was $token")
                }
                parser.requireToken(JsonToken.START_OBJECT)
                emit(parser.readValueAs(Item::class.java))
                token = parser.nextToken()
            }
            parser.requireToken(null)
        }
    }
}

fun JsonParser.requireToken(expected: JsonToken?) {
    val actual = nextToken()
    if (actual != expected) {
        throw JsonParseException(this, "Expected ${expected ?: "end of file"} but was $actual")
    }
}

翻閱 Jackson 的文檔后,發現這很容易。 創建 ObjectMapper 時我需要配置 YAMLFactory:

@SpringBootApplication
class Main {
    @Bean
    fun yamlMapper(): ObjectMapper =
        ObjectMapper(YAMLFactory.builder()
            .loaderOptions(LoaderOptions().apply {
                codePointLimit = 100 * 1024 * 1024 // 100MB
            })
        )
}

請參閱最大輸入 YAML 文檔大小 (3 MB)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM