我有一个 JSON 格式的 OData 响应(以几 MB 为单位),要求是流式传输“JSON 的某些部分”,甚至无需将它们加载到内存中。
例如:当我value[0].Body.Content
在下面的 JSON 中读取属性“”(将以 MB 为单位)时,我想将此值部分流式传输,而不将其反序列化为字符串类型的对象。所以基本上将值部分读入一个固定大小的字节数组并将该字节数组写入目标流(重复该步骤直到该数据完成处理)。
JSON:
{
"@odata.context": "https://localhost:5555/api/v2.0/$metadata#Me/Messages",
"value": [
{
"@odata.id": "https://localhost:5555/api/v2.0/",
"@odata.etag": "W/\"Something\"",
"Id": "vccvJHDSFds43hwy98fh",
"CreatedDateTime": "2018-12-01T01:47:53Z",
"LastModifiedDateTime": "2018-12-01T01:47:53Z",
"ChangeKey": "SDgf43tsdf",
"WebLink": "https://localhost:5555/?ItemID=dfsgsdfg9876ijhrf",
"Body": {
"ContentType": "HTML",
"Content": "<html>\r\n<body>Huge Data Here\r\n</body>\r\n</html>\r\n"
},
"ToRecipients": [{
"EmailAddress": {
"Name": "ME",
"Address": "me@me.com"
}
}
],
"CcRecipients": [],
"BccRecipients": [],
"ReplyTo": [],
"Flag": {
"FlagStatus": "NotFlagged"
}
}
],
"@odata.nextLink": "http://localhost:5555/rest/jersey/sleep?%24filter=LastDeliveredDateTime+ge+2018-12-01+and+LastDeliveredDateTime+lt+2018-12-02&%24top=50&%24skip=50"
}
尝试的方法:
1. Newtonsoft
我最初尝试使用 Newtonsoft 流,但它在内部将数据转换为字符串并加载到内存中。(这会导致 LOH 突然上升,并且在压缩发生之前内存不会被释放 - 我们的工作进程有内存限制,无法将其保存在内存中)
**code:**
using (var jsonTextReader = new JsonTextReader(sr))
{
var pool = new CustomArrayPool();
// Checking if pooling will help with memory
jsonTextReader.ArrayPool = pool;
while (jsonTextReader.Read())
{
if (jsonTextReader.TokenType == JsonToken.PropertyName
&& ((string)jsonTextReader.Value).Equals("value"))
{
jsonTextReader.Read();
if (jsonTextReader.TokenType == JsonToken.StartArray)
{
while (jsonTextReader.Read())
{
if (jsonTextReader.TokenType == JsonToken.StartObject)
{
var Current = JToken.Load(jsonTextReader);
// By Now, the LOH Shoots up.
// Avoid below code of converting this JToken back to byte array.
destinationStream.write(Encoding.ASCII.GetBytes(Current.ToString()));
}
else if (jsonTextReader.TokenType == JsonToken.EndArray)
{
break;
}
}
}
}
if (jsonTextReader.TokenType == JsonToken.StartObject)
{
var Current = JToken.Load(jsonTextReader);
// Do some processing with Current
destinationStream.write(Encoding.ASCII.GetBytes(Current.ToString()));
}
}
}
OData.Net:
我在想这是否可以使用 OData.Net 库,因为它看起来支持字符串字段的流式传输。但不能走得太远,因为我最终为数据创建了一个模型,这意味着该值将被转换为 MB 的一个字符串对象。
代码
ODataMessageReaderSettings settings = new ODataMessageReaderSettings(); IODataResponseMessage responseMessage = new InMemoryMessage { Stream = stream }; responseMessage.SetHeader("Content-Type", "application/json;odata.metadata=minimal;"); // ODataMessageReader reader = new ODataMessageReader((IODataResponseMessage)message, settings, GetEdmModel()); ODataMessageReader reader = new ODataMessageReader(responseMessage, settings, new EdmModel()); var oDataResourceReader = reader.CreateODataResourceReader(); var property = reader.ReadProperty();
知道如何使用 OData.Net/Newtonsoft 和某些字段的流值部分解析这个 JSON 吗?
这样做的唯一方法是手动解析流吗?