Json.NET:反序列化嵌套字典

时间:2011-06-20 18:58:26

标签: c# json serialization json.net deserialization

将对象反序列化为DictionaryJsonConvert.DeserializeObject<IDictionary<string,object>>(json))时,嵌套对象被反序列化为JObject s。是否可以强制嵌套对象反序列化为Dictionary

3 个答案:

答案 0 :(得分:38)

我找到了一种方法,通过提供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()});
    }
}

文档: CustomCreationConverter with Json.NET

答案 1 :(得分:1)

替代/更新:

我需要反序列化String的词典字典,并使用当前的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);

答案 2 :(得分:0)

当我遇到这个问题时,我有一个非常相似但略微复杂的需求。起初我以为我可以适应已接受的答案,但这似乎有点复杂,我最终采取了不同的方法。我试图将现代JSON层放在旧版C ++ API之上。我将为您保留详细信息,仅说要求可以归结为:

  • JSON对象成为Dictionary<string,object>

  • JSON数组变为List<object>

  • JSON值成为相应的原始CLR值。<​​/ p>

  • 对象和数组可以无限嵌套。

我首先将请求字符串反序列化为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()}");
        }
    }

我希望有人可以找到这种方法。