【问题标题】:How to work with a DynamicJsonObject's property values?如何使用动态 Json 对象属性值?
【发布时间】:2017-05-18 20:19:30
【问题描述】:

假设在我的 WebAPI 中,我收到了这样的 json:

{ 
    prop1: "sometext",
    prop2: 123,
    prop3: true, 
    prop4: [1,2,3,4,5],
    prop5: ["text1", "text2", "text3"]
}

为了处理这些数据,我将其转换为:dynamic data = System.Web.Helpers.Json.Decode(json);。在大多数情况下,使用它真的很容易,但我遇到了需要将这些数据重新传递到数据库的情况。大多数转换都非常简单,可以轻松地遍历 DynamicJsonObject 并将信息发送到数据库。

我的大问题是处理像prop4prop5 这样的属性。此数组正在转换为 DynamicJsonArray。要将其转换为原始数组,我目前正在使用这个:

Array arr = (Array) data["prop4"];
data["prop4"] = arr.Cast<Int32>().ToArray();

上面的代码工作正常,它成功地将属性值转换为可以发送到数据库的整数数组。但是,当我使用字符串数组时:

Array arr = (Array) data["prop5"];
data["prop5"] = arr.Cast<string>().ToArray();

data["prop5"] 的值没有改变,当我检查它的值时,它仍然指向System.Web.Helpers.DynamicJsonArray 类型。为什么会这样?

另外,我没有在 C# 中处理动态对象的经验,我使用它是因为在我的情况下,我并不总是知道我收到的 JSON 将具有哪些属性。有没有更清洁的方法来进行这种转换?实际上,是否有任何需要使用动态对象来处理 JSON?

编辑:

抱歉,非常不清楚。为了澄清事情,这就是我实际上正在做的事情:

  • 我正在使用通用函数调用来自参数data 的任何数据的数据库过程:

    public static IEnumerable<Dictionary<string, object>> CallDBProcedure(string proc, dynamic data)
    {
        using (NpgsqlConnection conn = new NpgsqlConnection(ConnStr))
        {
            try
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
    
                    cmd.CommandText = proc;
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
    
                    foreach (string property in data.GetDynamicMemberNames())
                    {
                        object propertyValue = data[property];
                        // The method convertNullValue returns the own value if it's not null
                        // and returns DBNull.Value if it's null. Every value must be properly 
                        // converted, but I can't directly convert a DynamicJsonArray.
                        cmd.Parameters.Add(new NpgsqlParameter(property, convertNullValue(propertyValue))); 
    
                    }
    
    
                    var reader = cmd.ExecuteReader();
    
                    return new DrToDictionary().Serialize(reader);
    
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                conn.Close();
            }
        }
    }
    
  • 然后,为了避免异常,我在处理data之前 我将它传递给CallDBProcedure,遍历 DynamicJsonObject 并将其中的每个 DynamicJsonArray 转换为原始数组:

    public static void ProcessData(dynamic data)
    {
        // Directly using data.GetDynamicMemberNames() and modifiying data
        // inside the loop causes an exception. Using a string list instead (hacky code?).
        List<string> properties = ((Dictionary<string, object>.KeyCollection) data.GetDynamicMemberNames()).ToList();
    
        foreach (string property in properties)
        {
            object propertyValue = data[property];
    
            if (propertyValue != null && propertyValue.GetType() == typeof(DynamicJsonArray))
            {
                Array arr = (Array)data[property];
    
                if (arr.Length == 0)
                {
                    // This works.
                    data[property] = null;
                }
                else
                {
                    // Discover the type of my array.
                    if (arr.GetValue(0) is int)
                    {
                        // This works.
                        data[property] = arr.Cast<Int32>().ToArray();
                    }
                    else
                    {
                        // This doesn't.
                        data[property] = arr.Cast<string>().ToArray();
                    }
                }
            }
        }
    }
    

现在我正在迭代data 两次。我知道必须有一种明显而简单的方法来让这个丑陋的代码更干净,但我只是没有看到它。

EDIT2:

我发现的一个解决方案是将字符串数组放入不同的变量中。然后我就可以正常使用它们了。我真的不明白为什么动态对象在某些情况下可以更改其类型,而在其他情况下却不能。

EDIT3:

忘了说我收到了这样的 json:dynamic data = System.Web.Helpers.Json.Decode(json);

【问题讨论】:

  • 佩德罗,你的问题不太清楚。你想达到什么目的? DynamicJsonArray 有什么问题,所以您需要将它们转换为原始数组类型?为什么要“就地”进行?您如何得知特定 JSON 包含 prop4 并且它的实际类型是“整数数组”?我认为如果没有“大局”,就很难回答您的问题。
  • Pedro,对于 [1,2,3,4,5]["text1", "text2", "text3"] 尝试转换为 Object[]ArrayList 而不是 Array
  • @BhavikJani [1,2,3,4,5]["text1", "text2", "text3"] 都以DynamicJsonArray 的身份出现。尝试了您建议的转换。当我转换为Object[] 时,该对象仍将其类型保持为DynamicJsonArray。当我尝试转换为 ArrayList 时,C# 告诉我无法将 DynamicJsonArray 转换为 ArrayList

标签: c# .net arrays json dynamicobject


【解决方案1】:

它只是读取从 API 返回的 json 对象。

例如

你可以使用

dynamic stuff = JsonConvert.DeserializeObject("{ 'prop1' : 'sometext', 'prop2': '123',
    'prop3': 'True'}");

string Prop1= stuff.First.Prop1;
string Prop2= stuff.First.Prop2;

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@""{ 'prop1' : 'sometext', 'prop2': '123',
    'prop3': 'True'}"");
Console.WriteLine(json.prop1);

Stackoverflow 中的另一个类似问题如下 How can I parse JSON with C#?

【讨论】:

    猜你喜欢
    • 2016-05-08
    • 2019-09-05
    • 2011-01-18
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 2018-08-13
    相关资源
    最近更新 更多