【问题标题】:Json.NET: Deserializing nested dictionariesJson.NET:反序列化嵌套字典
【发布时间】:2011-09-18 22:48:15
【问题描述】:

将对象反序列化为Dictionary (JsonConvert.DeserializeObject<IDictionary<string,object>>(json)) 时,嵌套对象将反序列化为JObjects。是否可以强制将嵌套对象反序列化为Dictionarys?

【问题讨论】:

  • 本文提供了一种将嵌套的 JSON 对象反序列化为字典的简单方法:buildplease.com/pages/json
  • 可能不是字典,但我自己一直在反序列化为 ExpandoObject 以获得相同的效果。

标签: c# json serialization json.net deserialization


【解决方案1】:

我有一个“未知”字典的嵌套/深层结构,它被序列化/反序列化到/来自 C# 对象和 JSON 字符串。 .NET 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);

【讨论】:

    【解决方案2】:

    当我遇到这个问题时,我有一个非常相似但稍微复杂一点的需求。起初我想也许我可以调整接受的答案,但这似乎有点复杂,我最终采取了不同的方法。我试图在遗留 C++ API 之上放置一个现代 JSON 层。我会省略你的细节,只是说要求归结为:

    • JSON 对象变为Dictionary&lt;string,object&gt;

    • JSON 数组变为 List&lt;object&gt;

    • 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()}");
            }
        }
    

    我希望有人能发现这种方法有用。

    【讨论】:

    • 这真的很有用。我无法使用给定的解决方案解码这种响应。 {"id":2,"name":"root","descendants":[{"id":4,"name":"node2","descendants":[{"id":7,"name" :"node21"},{"id":8,"name":"node22"}]},{"id":3,"name":"node1","descendants":[{"id":5 ,"name":"node11"},{"id":6,"name":"node12"}]}]}。谢谢
    【解决方案3】:

    替代/更新:

    我需要反序列化 Strings 的字典字典,并且使用当前的 Json.NET (5.0) 我不必创建 CustomConverter,我只是使用(在 VB.Net 中):

    JsonConvert.DeserializeObject(Of IDictionary(Of String, IDictionary(Of String, String)))(jsonString)
    

    或者,在 C# 中:

    JsonConvert.DeserializeObject<IDictionary<String, IDictionary<String, String>>(jsonString);
    

    【讨论】:

    • 这不支持正确转换递归/未知 json 结构。
    • 这没有回答,因为它专门指的是固定级别的嵌套
    【解决方案4】:

    我找到了一种通过提供CustomCreationConverter 实现将所有嵌套对象转换为Dictionary&lt;string,object&gt; 的方法:

    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()});
        }
    }
    

    文档:CustomCreationConverter with Json.NET

    【讨论】:

      猜你喜欢
      • 2014-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多