JObject를 사전으로 변환합니다. 가능합니까?
임의의 json payload를 받아들인 웹 API 메서드가 있습니다.JObject소유물.그래서 뭐가 올지 모르겠지만 로 번역해야 합니다.NET 타입한 잔 주세요.Dictionary<string,object>내가 하고 싶은 대로 할 수 있게 말이야
여러 번 찾아봤지만 아무것도 찾을 수 없었고 결국 키마다 값씩 변환하는 지저분한 방법을 시작하게 되었습니다.쉽게 할 수 있는 방법이 있을까요?
입력 ->
JObject person = new JObject(
new JProperty("Name", "John Smith"),
new JProperty("BirthDate", new DateTime(1983, 3, 20)),
new JProperty("Hobbies", new JArray("Play football", "Programming")),
new JProperty("Extra", new JObject(
new JProperty("Foo", 1),
new JProperty("Bar", new JArray(1, 2, 3))
)
)
감사합니다!
가지고 계신 경우JObject오브젝트, 다음이 동작할 수 있는 것은 다음과 같습니다.
JObject person;
var values = person.ToObject<Dictionary<string, object>>();
를 가지고 있지 않은 경우JObject를 사용하여 작성할 수 있습니다.Newtonsoft.Json.Linq확장 방법:
using Newtonsoft.Json.Linq;
var values = JObject.FromObject(person).ToObject<Dictionary<string, object>>();
그렇지 않으면 JSON 문자열을 사전으로 역직렬화하므로 이 답변이 올바른 방향을 가리킬 수 있습니다.
var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
어느 누구도 정확히 들어맞지 못했기 때문에 나는 결국 두 가지 답을 혼합해서 사용했다.
ToObject()는 JSON 개체의 첫 번째 수준의 속성을 수행할 수 있지만 중첩된 개체는 사전()으로 변환되지 않습니다.
ToObject()는 첫 번째 레벨의 속성으로 매우 좋기 때문에 모든 작업을 수동으로 수행할 필요도 없습니다.
코드는 다음과 같습니다.
public static class JObjectExtensions
{
public static IDictionary<string, object> ToDictionary(this JObject @object)
{
var result = @object.ToObject<Dictionary<string, object>>();
var JObjectKeys = (from r in result
let key = r.Key
let value = r.Value
where value.GetType() == typeof(JObject)
select key).ToList();
var JArrayKeys = (from r in result
let key = r.Key
let value = r.Value
where value.GetType() == typeof(JArray)
select key).ToList();
JArrayKeys.ForEach(key => result[key] = ((JArray)result[key]).Values().Select(x => ((JValue)x).Value).ToArray());
JObjectKeys.ForEach(key => result[key] = ToDictionary(result[key] as JObject));
return result;
}
}
동작하지 않는 엣지 케이스와 퍼포먼스가 최강의 품질이 아닐 수 있습니다.
감사합니다 여러분!
JArays/JObjects에 중첩된 JArrays를 재현하기 위해 코드를 수정했지만, @Nawaz가 지적한 바와 같이, 받아들여진 답변은 그렇지 않습니다.
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
public static class JsonConversionExtensions
{
public static IDictionary<string, object> ToDictionary(this JObject json)
{
var propertyValuePairs = json.ToObject<Dictionary<string, object>>();
ProcessJObjectProperties(propertyValuePairs);
ProcessJArrayProperties(propertyValuePairs);
return propertyValuePairs;
}
private static void ProcessJObjectProperties(IDictionary<string, object> propertyValuePairs)
{
var objectPropertyNames = (from property in propertyValuePairs
let propertyName = property.Key
let value = property.Value
where value is JObject
select propertyName).ToList();
objectPropertyNames.ForEach(propertyName => propertyValuePairs[propertyName] = ToDictionary((JObject) propertyValuePairs[propertyName]));
}
private static void ProcessJArrayProperties(IDictionary<string, object> propertyValuePairs)
{
var arrayPropertyNames = (from property in propertyValuePairs
let propertyName = property.Key
let value = property.Value
where value is JArray
select propertyName).ToList();
arrayPropertyNames.ForEach(propertyName => propertyValuePairs[propertyName] = ToArray((JArray) propertyValuePairs[propertyName]));
}
public static object[] ToArray(this JArray array)
{
return array.ToObject<object[]>().Select(ProcessArrayEntry).ToArray();
}
private static object ProcessArrayEntry(object value)
{
if (value is JObject)
{
return ToDictionary((JObject) value);
}
if (value is JArray)
{
return ToArray((JArray) value);
}
return value;
}
}
다음은 간단한 버전입니다.
public static object ToCollections(object o)
{
var jo = o as JObject;
if (jo != null) return jo.ToObject<IDictionary<string, object>>().ToDictionary(k => k.Key, v => ToCollections(v.Value));
var ja = o as JArray;
if (ja != null) return ja.ToObject<List<object>>().Select(ToCollections).ToList();
return o;
}
C# 7 을 사용하고 있는 경우는, 다음과 같은 패턴 매칭을 사용할 수 있습니다.
public static object ToCollections(object o)
{
if (o is JObject jo) return jo.ToObject<IDictionary<string, object>>().ToDictionary(k => k.Key, v => ToCollections(v.Value));
if (o is JArray ja) return ja.ToObject<List<object>>().Select(ToCollections).ToList();
return o;
}
확장 방법의 좋은 사용 사례로 들리네요.Json으로 변환하기 쉬운 것을 가지고 있었습니다.NET(고마워 NuGet!):
물론, 이것은 빠르게 함께 해킹됩니다. 정리하는 등의 작업이 필요합니다.
public static class JTokenExt
{
public static Dictionary<string, object>
Bagify(this JToken obj, string name = null)
{
name = name ?? "obj";
if(obj is JObject)
{
var asBag =
from prop in (obj as JObject).Properties()
let propName = prop.Name
let propValue = prop.Value is JValue
? new Dictionary<string,object>()
{
{prop.Name, prop.Value}
}
: prop.Value.Bagify(prop.Name)
select new KeyValuePair<string, object>(propName, propValue);
return asBag.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
if(obj is JArray)
{
var vals = (obj as JArray).Values();
var alldicts = vals
.SelectMany(val => val.Bagify(name))
.Select(x => x.Value)
.ToArray();
return new Dictionary<string,object>()
{
{name, (object)alldicts}
};
}
if(obj is JValue)
{
return new Dictionary<string,object>()
{
{name, (obj as JValue)}
};
}
return new Dictionary<string,object>()
{
{name, null}
};
}
}
언급URL : https://stackoverflow.com/questions/14886800/convert-jobject-into-dictionarystring-object-is-it-possible
'sourcecode' 카테고리의 다른 글
| woocommerce에 모든 주문을 볼 수 있는 쇼트 코드/페이지가 있습니까? (0) | 2023.02.11 |
|---|---|
| WordPress REST API에서 원시 HTML 출력 가져오기 (0) | 2023.02.07 |
| Word press - get_results() - 실패 또는 비어 있는지 확인하는 방법 (0) | 2023.02.07 |
| 필요한 위치에 있지 않고 콘텐츠 상단에 쇼트코드가 표시됨 (0) | 2023.02.07 |
| WordPress에서 CloudConvert API 사용 (0) | 2023.02.07 |