C# 평탄화 json 구조
C#(Newtonsoft로 표시됨)에 json-object가 있습니다.Json.Linq.JObject 객체)를 사용하여 사전에 평평하게 만들어야 합니다.예를 들어 설명하겠습니다.
{
"name": "test",
"father": {
"name": "test2"
"age": 13,
"dog": {
"color": "brown"
}
}
}
그러면 다음과 같은 키-값 쌍이 있는 사전이 생성됩니다.
["name"] == "test",
["father.name"] == "test2",
["father.age"] == 13,
["father.dog.color"] == "brown"
이거 어떻게 해?
JObject jsonObject=JObject.Parse(theJsonString);
IEnumerable<JToken> jTokens = jsonObject.Descendants().Where(p => !p.HasValues);
Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
{
properties.Add(jToken.Path, jToken.ToString());
return properties;
});
네스트된 json 구조를 사전 객체에 평평하게 하는 것과 같은 요건이 있었습니다.여기서 해결책을 찾았습니다.
.NET에서는 Core 3.0이 하나의 방법입니다(Json).NET은 필요 없습니다).이건 분명 쉬워질 거야.
using System.Linq;
using System.Text.Json;
(...)
public static Dictionary<string, JsonElement> GetFlat(string json)
{
IEnumerable<(string Path, JsonProperty P)> GetLeaves(string path, JsonProperty p)
=> p.Value.ValueKind != JsonValueKind.Object
? new[] { (Path: path == null ? p.Name : path + "." + p.Name, p) }
: p.Value.EnumerateObject() .SelectMany(child => GetLeaves(path == null ? p.Name : path + "." + p.Name, child));
using (JsonDocument document = JsonDocument.Parse(json)) // Optional JsonDocumentOptions options
return document.RootElement.EnumerateObject()
.SelectMany(p => GetLeaves(null, p))
.ToDictionary(k => k.Path, v => v.P.Value.Clone()); //Clone so that we can use the values outside of using
}
보다 표현력이 풍부한 버전을 다음에 나타냅니다.
시험
using System.Linq;
using System.Text.Json;
(...)
var json = @"{
""name"": ""test"",
""father"": {
""name"": ""test2"",
""age"": 13,
""dog"": {
""color"": ""brown""
}
}
}";
var d = GetFlat(json);
var options2 = new JsonSerializerOptions { WriteIndented = true };
Console.WriteLine(JsonSerializer.Serialize(d, options2));
산출량
{
"name": "test",
"father.name": "test2",
"father.age": 13,
"father.dog.color": "brown"
}
보다 표현력 높은 버전
using System.Linq;
using System.Text.Json;
(...)
static Dictionary<string, JsonElement> GetFlat(string json)
{
using (JsonDocument document = JsonDocument.Parse(json))
{
return document.RootElement.EnumerateObject()
.SelectMany(p => GetLeaves(null, p))
.ToDictionary(k => k.Path, v => v.P.Value.Clone()); //Clone so that we can use the values outside of using
}
}
static IEnumerable<(string Path, JsonProperty P)> GetLeaves(string path, JsonProperty p)
{
path = (path == null) ? p.Name : path + "." + p.Name;
if (p.Value.ValueKind != JsonValueKind.Object)
yield return (Path: path, P: p);
else
foreach (JsonProperty child in p.Value.EnumerateObject())
foreach (var leaf in GetLeaves(path, child))
yield return leaf;
}
사실 오늘 아침 SO에서 이 질문을 찾을 수 없었고 결국 저만의 확장 방법을 써서 반품하게 되었습니다.JValue
JSON BLOB의 리프 노드 값을 포함하는 객체.일부 개선점을 제외하면 승인된 답변과 유사합니다.
- JSON 객체뿐만 아니라 사용자가 지정한 모든 JSON(어레이, 속성 등)을 처리합니다.
- 메모리 사용량 감소
- 호출 없음
.Count()
결국 필요하지 않은 후손에게
사용 사례에 따라 관련이 있을 수도 있고 없을 수도 있지만, 제 경우에 해당됩니다.나는 JSON을 평평하게 만드는 법을 배웠다.블로그의 NET 오브젝트제가 쓴 확장 방법은 다음과 같습니다.
public static class JExtensions
{
public static IEnumerable<JValue> GetLeafValues(this JToken jToken)
{
if (jToken is JValue jValue)
{
yield return jValue;
}
else if (jToken is JArray jArray)
{
foreach (var result in GetLeafValuesFromJArray(jArray))
{
yield return result;
}
}
else if (jToken is JProperty jProperty)
{
foreach (var result in GetLeafValuesFromJProperty(jProperty))
{
yield return result;
}
}
else if (jToken is JObject jObject)
{
foreach (var result in GetLeafValuesFromJObject(jObject))
{
yield return result;
}
}
}
#region Private helpers
static IEnumerable<JValue> GetLeafValuesFromJArray(JArray jArray)
{
for (var i = 0; i < jArray.Count; i++)
{
foreach (var result in GetLeafValues(jArray[i]))
{
yield return result;
}
}
}
static IEnumerable<JValue> GetLeafValuesFromJProperty(JProperty jProperty)
{
foreach (var result in GetLeafValues(jProperty.Value))
{
yield return result;
}
}
static IEnumerable<JValue> GetLeafValuesFromJObject(JObject jObject)
{
foreach (var jToken in jObject.Children())
{
foreach (var result in GetLeafValues(jToken))
{
yield return result;
}
}
}
#endregion
}
그럼 내 통화 코드에서, 난 그냥 그 코드를Path
그리고.Value
로부터의JValue
반환된 객체:
var jToken = JToken.Parse("blah blah json here");
foreach (var jValue in jToken.GetLeafValues())
{
Console.WriteLine("{0} = {1}", jValue.Path, jValue.Value);
}
https://github.com/jsonfx/jsonfx을 사용하여 json을 동적 개체로 역직렬화할 수 있습니다.그런 다음 Expando Object를 사용하여 원하는 것을 얻습니다.
public Class1()
{
string json = @"{
""name"": ""test"",
""father"": {
""name"": ""test2"",
""age"": 13,
""dog"": {
""color"": ""brown""
}
}
}";
var reader = new JsonFx.Json.JsonReader();
dynamic output = reader.Read(json);
Dictionary<string, object> dict = new Dictionary<string, object>();
GenerateDictionary((System.Dynamic.ExpandoObject) output, dict, "");
}
private void GenerateDictionary(System.Dynamic.ExpandoObject output, Dictionary<string, object> dict, string parent)
{
foreach (var v in output)
{
string key = parent + v.Key;
object o = v.Value;
if (o.GetType() == typeof(System.Dynamic.ExpandoObject))
{
GenerateDictionary((System.Dynamic.ExpandoObject)o, dict, key + ".");
}
else
{
if (!dict.ContainsKey(key))
{
dict.Add(key, o);
}
}
}
}
JSONPath를 사용할 수 있습니다.$..*
JSON 구조의 모든 멤버를 가져오고 하위 항목이 없는 멤버를 필터링하여 컨테이너 속성을 건너뜁니다.
예.
var schemaObject = JObject.Parse(schema);
var values = schemaObject
.SelectTokens("$..*")
.Where(t => !t.HasValues)
.ToDictionary(t => t.Path, t => t.ToString());
tymtam이 제공하는 코드와 지원되는 어레이를 기반으로 합니다.
public static IEnumerable<KeyValuePair<string, string>> Flatten<T>(this T data, string seperator = ":") where T : class
{
var json = JsonSerializer.Serialize(data);
string GetArrayPath(string path, string name, int idx) =>
path == null ? $"{name}{seperator}{idx}" : $"{path}{seperator}{name}{seperator}{idx}";
IEnumerable<(string Path, JsonElement Element)> GetLeaves(string path, string name, JsonElement element) => element.ValueKind switch
{
JsonValueKind.Object => element.EnumerateObject()
.SelectMany(child => GetLeaves(path == null ? name : $"{path}{seperator}{name}", child.Name, child.Value)),
JsonValueKind.Array => element.EnumerateArray()
.SelectMany((child, idx) => child.ValueKind == JsonValueKind.Object
? child.EnumerateObject().SelectMany(child => GetLeaves(GetArrayPath(path, name, idx), child.Name, child.Value))
: new[] { (Path: GetArrayPath(path, name, idx), child) }
),
_ => new[] { (Path: path == null ? name : $"{path}{seperator}{name}", element) },
};
using JsonDocument document = JsonDocument.Parse(json); // Optional JsonDocumentOptions options
return document.RootElement.EnumerateObject()
.SelectMany(p => GetLeaves(null, p.Name, p.Value))
.ToDictionary(k => k.Path, v => v.Element.Clone().ToString()); //Clone so that we can use the values outside of using
}
언급URL : https://stackoverflow.com/questions/7394551/c-sharp-flattening-json-structure
'programing' 카테고리의 다른 글
Postgres 고유 제약 조건과 인덱스 비교 (0) | 2023.04.13 |
---|---|
Windows에서 bat 파일을 사용하여 폴더와 모든 콘텐츠를 삭제하려면 어떻게 해야 합니까? (0) | 2023.04.13 |
Python boto3를 사용하여 S3에서 JSON 파일 읽기 (0) | 2023.04.03 |
Word press에서 태그 링크를 재생하는 방법 (0) | 2023.04.03 |
경고 해결 방법: 리액트가 DOM 요소의 X 프로펠을 인식하지 않음 (0) | 2023.04.03 |