Json.NET: 중첩된 사전을 역직렬화하는 중
오브젝트를 에 역직렬화할 때Dictionary
(JsonConvert.DeserializeObject<IDictionary<string,object>>(json)
) 네스트된 오브젝트는 에 역직렬화 됩니다.JObject
s. 중첩된 오브젝트를 강제로 역직렬화 할 수 있습니까?Dictionary
s?
네스트된 모든 오브젝트를Dictionary<string,object>
을 제공함으로써CustomCreationConverter
구현:
class MyConverter : CustomCreationConverter<IDictionary<string, object>>
{
public override IDictionary<string, object> Create(Type objectType)
{
return new Dictionary<string, object>();
}
public override bool CanConvert(Type objectType)
{
// in addition to handling IDictionary<string, object>
// we want to handle the deserialization of dict value
// which is of type object
return objectType == typeof(object) || base.CanConvert(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject
|| reader.TokenType == JsonToken.Null)
return base.ReadJson(reader, objectType, existingValue, serializer);
// if the next token is not an object
// then fall back on standard deserializer (strings, numbers etc.)
return serializer.Deserialize(reader);
}
}
class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText(@"c:\test.json");
var obj = JsonConvert.DeserializeObject<IDictionary<string, object>>(
json, new JsonConverter[] {new MyConverter()});
}
}
문서:Custom Creation Converter with Json.네트워크
이 Q를 접했을 때, 저는 매우 비슷하지만 조금 더 복잡한 요구를 가지고 있었습니다.처음에는 인정된 답변을 받아들일 수 있을 거라고 생각했지만, 조금 복잡해 보였고, 결국 다른 접근법을 택하게 되었습니다.레거시 C++ API 위에 현대적인 JSON 레이어를 추가하려고 했습니다.자세한 내용은 생략하고 요건은 다음과 같습니다.
JSON 오브젝트는
Dictionary<string,object>
.JSON 어레이는
List<object>
.JSON 값은 대응하는 프리미티브 CLR 값이 됩니다.
개체와 배열을 무한히 중첩할 수 있습니다.
먼저 요청 문자열을 Newtonsoft JSON 개체로 역직렬화한 후 위의 요건에 따라 메서드를 호출하여 변환합니다.
var jsonObject = JsonConvert.DeserializeObject(requestString);
var apiRequest = ToApiRequest(jsonObject);
// call the legacy C++ API ...
API가 기대하는 구조로 변환하는 메서드는 다음과 같습니다.
private static object ToApiRequest(object requestObject)
{
switch (requestObject)
{
case JObject jObject: // objects become Dictionary<string,object>
return ((IEnumerable<KeyValuePair<string, JToken>>) jObject).ToDictionary(j => j.Key, j => ToApiRequest(j.Value));
case JArray jArray: // arrays become List<object>
return jArray.Select(ToApiRequest).ToList();
case JValue jValue: // values just become the value
return jValue.Value;
default: // don't know what to do here
throw new Exception($"Unsupported type: {requestObject.GetType()}");
}
}
나는 누군가가 이 접근법을 유용하게 여겨주길 바란다.
대체/업데이트:
나는 사전의 직역을 해제할 필요가 있었다.String
s 및 현재 Json을 사용합니다.NET(5.0) Custom Converter를 작성할 필요가 없고 (VB에서) 사용했을 뿐입니다.넷):
JsonConvert.DeserializeObject(Of IDictionary(Of String, IDictionary(Of String, String)))(jsonString)
또는 C#에서:
JsonConvert.DeserializeObject<IDictionary<String, IDictionary<String, String>>(jsonString);
C# 객체와 JSON 문자열 사이에서 시리얼화/비직렬화되는 "알 수 없는" 사전의 중첩/심층 구조를 가지고 있습니다.넷 5
사용하는 경우Newtonsoft
자동으로 동작하지 않습니다.
사용하는 경우System.Text.Json
자동으로 동작합니다.
//does NOT work (newtonDeserialized does not have the same data in the nested Dictionaries as in object):
var newtonSerialized = Newtonsoft.Json.JsonConvert.SerializeObject(object);
var newtonDeserialized = Newtonsoft.Json.JsonConvert.DeserializeObject<WaitlistResponse>(newtonSerialized);
//Works (netDeserialized have the same data in the nested Directories as in object):
var netSerialized = System.Text.Json.JsonSerializer.Serialize(object);
var netDeserialized = System.Text.Json.JsonSerializer.Deserialize<WaitlistResponse>(netSerialized);
@AlexD가 수용하는 솔루션은 json에 어레이가 있는 경우 이상적으로 동작하지 않습니다.a를 반환한다.JArray
의JObject
대신List<Dictionary<string, object>>
이 문제는 ReadJson() 메서드를 수정함으로써 해결할 수 있습니다.
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject || reader.TokenType == JsonToken.Null)
return base.ReadJson(reader, objectType, existingValue, serializer);
//if it's an array serialize it as a list of dictionaries
if(reader.TokenType == JsonToken.ArrayStart)
return serializer.Deserialize(reader, typeof(List<Dictionary<string, object>>));
// if the next token is not an object
// then fall back on standard deserializer (strings, numbers etc.)
return serializer.Deserialize(reader);
}
내 경우 모든 것이 중첩된 사전은 아니다.또한 기본 유형의 키 값인 배열이 있으며 배열의 개체가 사전이 아닌 경우 예외가 발생합니다.
그래서 Phillip S의 답변을 바탕으로 해서
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject || reader.TokenType == JsonToken.Null)
return base.ReadJson(reader, objectType, existingValue, serializer);
//if it's an array serialize it as a list of dictionaries
if (reader.TokenType == JsonToken.StartArray)
{
return serializer.Deserialize(reader, typeof(List<object>)); // instead of List<Dictionary<string, object>>
}
// if the next token is not an object
// then fall back on standard deserializer (strings, numbers etc.)
return serializer.Deserialize(reader);
}
아직 작동되지 않은 사람들에게 도움이 되길 바랍니다.
언급URL : https://stackoverflow.com/questions/6416017/json-net-deserializing-nested-dictionaries
'programing' 카테고리의 다른 글
React의 인라인 CSS 스타일: 미디어 쿼리를 구현하는 방법 (0) | 2023.04.05 |
---|---|
코드의 ASP.NET Core appsettings.json 업데이트 (0) | 2023.04.05 |
JSONP에서 .ajax()를 사용하는 기본적인 예? (0) | 2023.04.05 |
Windows Azure 동적 콘텐츠에서 gzip HTTP 압축을 활성화하는 방법 (0) | 2023.03.31 |
다음 js - 일부 페이지에서 서버 측 렌더링을 비활성화합니다. (0) | 2023.03.31 |