json 어레이 스트림을 한 번에 하나씩 역직렬화
큰 오브젝트의 배열을 json http 응답 스트림으로 시리얼화합니다.이 오브젝트를 스트림에서1개씩 역직렬화 합니다.이것을 할 수 있는 c# 라이브러리가 있나요?json.net에서 확인했는데 전체 객체 어레이를 한 번에 역직렬화해야 할 것 같습니다.
[{large json object},{large json object}.....]
설명:스트림에서 json 개체를 하나씩 읽고 역직렬화하려고 합니다.
JSON을 증분적으로 읽으려면JsonTextReader와 조합하여StreamReader단, 반드시 리더에서 모든 JSON을 수동으로 읽을 필요는 없습니다.Linq-To-JSON API를 활용하여 리더에서 큰 개체를 로드하여 보다 쉽게 작업할 수 있어야 합니다.
예를 들어 다음과 같은 JSON 파일이 있다고 가정해 보겠습니다.
[
{
"name": "foo",
"id": 1
},
{
"name": "bar",
"id": 2
},
{
"name": "baz",
"id": 3
}
]
파일에서 증분적으로 읽는 코드는 다음과 같습니다.(이 경우 FileStream을 응답 스트림으로 바꿉니다.)
using (FileStream fs = new FileStream(@"C:\temp\data.json", FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs))
using (JsonTextReader reader = new JsonTextReader(sr))
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
// Load each object from the stream and do something with it
JObject obj = JObject.Load(reader);
Console.WriteLine(obj["id"] + " - " + obj["name"]);
}
}
}
위의 출력은 다음과 같습니다.
1 - foo
2 - bar
3 - baz
파서/디시리얼라이저의 샘플/테스트 중 하나를 단순화하여 이 질문의 사용 사례에 보다 쉽게 답변했습니다.
테스트 데이터에 대해서는 다음과 같습니다.
https://github.com/ysharplanguage/FastJsonParser/tree/master/JsonTest/TestData
(fathers.json.txt 참조)
샘플 코드는 다음과 같습니다.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
// Our stuff
using System.Text.Json;
//...
public class FathersData
{
public Father[] fathers { get; set; }
}
public class Someone
{
public string name { get; set; }
}
public class Father : Someone
{
public int id { get; set; }
public bool married { get; set; }
// Lists...
public List<Son> sons { get; set; }
// ... or arrays for collections, that's fine:
public Daughter[] daughters { get; set; }
}
public class Child : Someone
{
public int age { get; set; }
}
public class Son : Child
{
}
public class Daughter : Child
{
public string maidenName { get; set; }
}
//...
static void FilteredFatherStreamTestSimplified()
{
// Get our parser:
var parser = new JsonParser();
// (Note this will be invoked thanks to the "filters" dictionary below)
Func<object, object> filteredFatherStreamCallback = obj =>
{
Father father = (obj as Father);
// Output only the individual fathers that the filters decided to keep (i.e., when obj.Type equals typeof(Father)),
// but don't output (even once) the resulting array (i.e., when obj.Type equals typeof(Father[])):
if (father != null)
{
Console.WriteLine("\t\tId : {0}\t\tName : {1}", father.id, father.name);
}
// Do not project the filtered data in any specific way otherwise,
// just return it deserialized as-is:
return obj;
};
// Prepare our filter, and thus:
// 1) we want only the last five (5) fathers (array index in the resulting "Father[]" >= 29,995),
// (assuming we somehow have prior knowledge that the total count is 30,000)
// and for each of them,
// 2) we're interested in deserializing them with only their "id" and "name" properties
var filters =
new Dictionary<Type, Func<Type, object, object, int, Func<object, object>>>
{
// We don't care about anything but these 2 properties:
{
typeof(Father), // Note the type
(type, obj, key, index) =>
((key as string) == "id" || (key as string) == "name") ?
filteredFatherStreamCallback :
JsonParser.Skip
},
// We want to pick only the last 5 fathers from the source:
{
typeof(Father[]), // Note the type
(type, obj, key, index) =>
(index >= 29995) ?
filteredFatherStreamCallback :
JsonParser.Skip
}
};
// Read, parse, and deserialize fathers.json.txt in a streamed fashion,
// and using the above filters, along with the callback we've set up:
using (var reader = new System.IO.StreamReader(FATHERS_TEST_FILE_PATH))
{
FathersData data = parser.Parse<FathersData>(reader, filters);
System.Diagnostics.Debug.Assert
(
(data != null) &&
(data.fathers != null) &&
(data.fathers.Length == 5)
);
foreach (var i in Enumerable.Range(29995, 5))
System.Diagnostics.Debug.Assert
(
(data.fathers[i - 29995].id == i) &&
!String.IsNullOrEmpty(data.fathers[i - 29995].name)
);
}
Console.ReadKey();
}
나머지 비트는 다음 위치에서 사용할 수 있습니다.
https://github.com/ysharplanguage/FastJsonParser
'HTH'
이 솔루션은 다양한 소스로부터 조합되어 있지만, 주로 Brian Rogers 솔루션에 근거하고 있습니다.대용량의 JSON 파일(개체 배열)을 임의의 범용 객체의 XML 파일로 변환합니다.
JSON은 다음과 같습니다.
{
"Order": [
{ order object 1},
{ order object 2},
{...}
{ order object 10000},
]
}
출력 XML:
<Order>...</Order>
<Order>...</Order>
<Order>...</Order>
C# 코드:
XmlWriterSettings xws = new XmlWriterSettings { OmitXmlDeclaration = true };
using (StreamWriter sw = new StreamWriter(xmlFile))
using (FileStream fs = new FileStream(jsonFile, FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs))
using (JsonTextReader reader = new JsonTextReader(sr))
{
//sw.Write("<root>");
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartArray)
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
JObject obj = JObject.Load(reader);
XmlDocument doc = JsonConvert.DeserializeXmlNode(obj.ToString(), "Order");
sw.Write(doc.InnerXml); // a line of XML code <Order>...</Order>
sw.Write("\n");
//this approach produces not strictly valid XML document
//add root element at the beginning and at the end to make it valid XML
}
}
}
}
//sw.Write("</root>");
}
오픈 소스 라이브러리인 Cinchoo ETL을 사용하면 메모리 설치 공간을 줄이고 대용량 JSON을 효율적으로 해석할 수 있습니다.개체는 스트림 기반 풀 모델에서 생성 및 반환되므로
using (var p = new ChoJSONReader(** YOUR JSON FILE **))
{
foreach (var rec in p)
{
Console.WriteLine($"Name: {rec.name}, Id: {rec.id}");
}
}
자세한 내용은 코드프로젝트 기사를 참조하십시오.
도움이 됐으면 좋겠다.
오래된 질문인 건 알지만 구글 검색에도 뜨기 때문에 최근에도 같은 질문이 필요했습니다.스트림의 serilization에 대처하는 또 다른 방법은 JsonSerializer를 사용하는 것입니다.역직렬화비동기 계산 가능
용도는 다음과 같습니다.
await using (var readStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
await foreach (T item in JsonSerializer.DeserializeAsyncEnumerable<T>(readStream))
{
// do something withe the item
}
}
언급URL : https://stackoverflow.com/questions/20374083/deserialize-json-array-stream-one-item-at-a-time
'programing' 카테고리의 다른 글
| ng각 2에서 작동하지 않는 텍스트 영역 모델 (0) | 2023.03.18 |
|---|---|
| WP -- 카테고리별로 투고를 취득하시겠습니까? (0) | 2023.03.18 |
| 워드프레스에서 mysql 쿼리를 실행하려면 어떻게 해야 하나요? (0) | 2023.03.18 |
| 샘플 스프링 부트애플리케이션의 필드에 로거를 주입하려면 어떻게 해야 합니까? (0) | 2023.03.18 |
| SQL ROWNUM 특정 범위 사이의 행을 반환하는 방법 (0) | 2023.03.18 |