从json中过滤坏的json值,以节省内存的方式



我们有一些不好的json,我们试图解析。不幸的是,它不是有效的json,因为它在有效载荷中返回未引号的NaN

我们正在从长期弃用的request库切换到axios库。这似乎使我们当前固定此有效负载的方法的内存使用量增加了一倍,但是我们的环境是内存受限的。文件是19MB,我们的约束是50MB。我认为与正则表达式的/解析有关的东西是在内存中复制json,除了axios试图做的解析之外。

我们在axios周围使用包装器,因此直接与它交互是有限的。我必须重新实现部分包装器才能访问它,它是一个外部内部库。

我知道我们要保留的键,所以丢弃结构的其余部分而不是处理NaN实际上是更可取的。

我们想要的结构,看起来像DataUsages[]

export interface DataUsages {
dataUsageId: string;
dataUsageName: string;
}

我们得到的结构在数组中的对象中有额外的项,我们根本不关心"dataUsageDownstreamUsages",这个键可以而且正在被丢弃'

[
{
"dataUsageId": "42",
"dataUsageName": "myname",
"dataUsageDownstreamUsages": [NaN]
}
]
目前

这是我们当前的方法

const reg1 = /[NaN]|NaN/gm
const parsed: EDMDataUsages[] = JSON.parse(
requireNonNullish(response.body, 'body').replace(reg1, '""').replace(/NAN/gm, ''),
)   

stream-json

现在我正在考虑使用stream-json

如果我使用解析器,它会退出,大概当它达到NaN时。所以我在看disassembler,但我不明白如何做到这一点。

const read = new Readable()
read.push(requireNonNullish(response.body, 'body'))
read.push(null)
const pipeline = chain([read, disassembler(), pick({ filter: 'data' }), data => this.log.trace('data', data)])
pipeline.on('data', data => this.log.trace('filter', data))

显然这段代码是不完整的

其他库也是可以接受的。请提供一个完整的例子。

好的,首先让我们创建一个伪数据

function genreateFakeData() {
const payload = { res: [] }
const mock = {
"dataUsageId": "42",
"dataUsageName": "myname",
"dataUsageDownstreamUsages": [NaN]
}
let totalFileSize = 0;
const fileSize = 19;
const SIZE_IN_BYTES = JSON.stringify(mock).length;
const SIZE_IN_MB = SIZE_IN_BYTES / 1024 / 1024;
while (totalFileSize < fileSize) {
totalFileSize += SIZE_IN_MB;
payload.res.push(mock);
}
fs.appendFileSync('fake.json', JSON.stringify(payload));
}

然后测试文件的大小是否正确

> ls -ltrh | grep fake
-rw-r--r--   1 naor.tedgi  staff    19M Jun 15 09:34 fake.json

让我们在堆约束下运行node应用程序并改变原始响应

node --max-old-space-size=50 index.js

index.js

const stream = require('stream');
const fs = require('fs');
const data = JSON.parse(fs.readFileSync('fake.json',{encoding:'utf8', flag:'r'}));
data.res.forEach(entry=>{
delete entry.dataUsageDownstreamUsages
})
console.log(data)

最新更新