當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
用Jackson编写大型JSON文件
生活随笔
收集整理的這篇文章主要介紹了
用Jackson编写大型JSON文件
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
有時(shí)您需要將大量數(shù)據(jù)導(dǎo)出到JSON到文件中。 可能是“將所有數(shù)據(jù)導(dǎo)出到JSON”,或者是GDPR“可移植性權(quán)利”,您實(shí)際上需要這樣做。
與任何大型數(shù)據(jù)集一樣,您不能只將其全部容納在內(nèi)存中并將其寫入文件。 它需要一段時(shí)間,它會(huì)從數(shù)據(jù)庫中讀取大量條目,并且您需要注意不要使此類導(dǎo)出使整個(gè)系統(tǒng)超載或耗盡內(nèi)存。
幸運(yùn)的是,借助Jackson的SequenceWriter和可選的管道流,這樣做非常簡單。 看起來像這樣:
private ObjectMapper jsonMapper = new ObjectMapper();private ExecutorService executorService = Executors.newFixedThreadPool(5);@Asyncpublic ListenableFuture<Boolean> export(UUID customerId) {try (PipedInputStream in = new PipedInputStream();PipedOutputStream pipedOut = new PipedOutputStream(in);GZIPOutputStream out = new GZIPOutputStream(pipedOut)) {Stopwatch stopwatch = Stopwatch.createStarted();ObjectWriter writer = jsonMapper.writer().withDefaultPrettyPrinter();try(SequenceWriter sequenceWriter = writer.writeValues(out)) {sequenceWriter.init(true);Future<?> storageFuture = executorService.submit(() ->storageProvider.storeFile(getFilePath(customerId), in));int batchCounter = 0;while (true) {List<Record> batch = readDatabaseBatch(batchCounter++);for (Record record : batch) {sequenceWriter.write(entry);}}// wait for storing to completestorageFuture.get();} logger.info("Exporting took {} seconds", stopwatch.stop().elapsed(TimeUnit.SECONDS));return AsyncResult.forValue(true);} catch (Exception ex) {logger.error("Failed to export data", ex);return AsyncResult.forValue(false);}}該代碼可以做一些事情:
- 使用SequenceWriter連續(xù)寫入記錄。 它使用OutputStream初始化,所有內(nèi)容均寫入其中。 這可以是簡單的FileOutputStream,也可以是如下所述的管道流。 注意,這里的命名有點(diǎn)誤導(dǎo)– writeValues(out)聽起來像是您指示作者現(xiàn)在寫東西; 而是將其配置為以后使用特定的流。
- SequenceWriter初始化為true ,表示“包裝在數(shù)組中”。 您正在編寫許多相同的記錄,因此它們應(yīng)在最終JSON中表示一個(gè)數(shù)組。
- 使用PipedOutputStream和PipedInputStream將SequenceWriter鏈接到InputStream ,然后將InputStream傳遞到存儲(chǔ)服務(wù)。 如果我們明確地處理文件,則不需要這樣做-只需傳遞FileOutputStream就可以。 但是,您可能希望以不同的方式存儲(chǔ)文件,例如在Amazon S3中,并且putObject調(diào)用需要一個(gè)InputStream,從該InputStream可以讀取數(shù)據(jù)并將其存儲(chǔ)在S3中。 因此,實(shí)際上,您正在寫入一個(gè)OutputStream,而該OutputStream會(huì)直接寫入InputStream,當(dāng)被輸入以讀取該輸入流時(shí),會(huì)將所有內(nèi)容寫入另一個(gè)OutputStream
- 存儲(chǔ)文件是在單獨(dú)的線程中調(diào)用的,因此寫入文件不會(huì)阻塞當(dāng)前線程,當(dāng)前線程的目的是從數(shù)據(jù)庫中讀取數(shù)據(jù)。 同樣,如果使用簡單的FileOutputStream,則不需要這樣做。
- 整個(gè)方法被標(biāo)記為@Async(spring),因此它不會(huì)阻止執(zhí)行-它被調(diào)用并在準(zhǔn)備就緒時(shí)完成(使用內(nèi)部Spring executor服務(wù)和有限的線程池)
- 這里未顯示數(shù)據(jù)庫批處理讀取代碼,因?yàn)樗S數(shù)據(jù)庫的不同而不同。 關(guān)鍵是,您應(yīng)該分批提取數(shù)據(jù),而不是SELECT * FROMX。
- OutputStream包裝在GZIPOutputStream中,因?yàn)閹в兄貜?fù)元素的JSON之類的文本文件可從壓縮中顯著受益
主要工作是由Jackson的SequenceWriter完成的,(顯而易見的)一點(diǎn)是–不要假設(shè)您的數(shù)據(jù)可以容納在內(nèi)存中。 它幾乎永遠(yuǎn)不會(huì)做,所以批量處理和增量寫入都是如此。
翻譯自: https://www.javacodegeeks.com/2018/08/writing-big-json-files-jackson.html
總結(jié)
以上是生活随笔為你收集整理的用Jackson编写大型JSON文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (金泉一号备案)
- 下一篇: gradle idea java ssm