将JObject转换为Dictionary <string,object>.可能吗?

tuc*_*caz 64 .net c# json json.net

我有一个Web API方法,它接受一个JObject属性的任意json有效负载.因此我不知道将要发生什么,但我仍然需要将其转换为.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))
    )
)
Run Code Online (Sandbox Code Playgroud)

谢谢!

Dan*_*ker 112

如果您有JObject对象,则以下操作可能有效:

JObject person;
var values = person.ToObject<Dictionary<string, object>>();
Run Code Online (Sandbox Code Playgroud)

如果您没有JObject,可以使用Newtonsoft.Json.Linq扩展方法创建一个:

using Newtonsoft.Json.Linq;

var values = JObject.FromObject(person).ToObject<Dictionary<string, object>>();
Run Code Online (Sandbox Code Playgroud)

否则,这个答案可能会指向正确的方向,因为它将JSON字符串反序列化为Dictionary.

var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
Run Code Online (Sandbox Code Playgroud)

  • `DeserializeObject&lt;Dictionary&lt;string, object&gt;&gt;` 对我来说非常有用;我最终通过“DeserializeObject&lt;Dictionary&lt;string, object&gt;[]&gt;”将其转换为满足我需要的字典数组。 (2认同)

tuc*_*caz 23

我最终使用了两个答案的混合,因为没有人真的把它钉在上面.

ToObject()可以在JSON对象中执行第一级属性,但嵌套对象不会转换为Dictionary().

也没有必要手动完成所有操作,因为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

它可能有边缘情况,它将无法工作,性能不是最强的质量.

多谢你们!


Uli*_*Uli 15

这是初始版本:我已经修改了代码,以便将JArrays与嵌套在 JArrays/JObjects 中的 JObjects相提并论,但是@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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Esb*_*sen 9

这是一个更简单的版本:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

如果使用 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;
    }
Run Code Online (Sandbox Code Playgroud)