【问题标题】:ASP.NET getting indexed values when deserializing JSON into a dynamic object将 JSON 反序列化为动态对象时,ASP.NET 获取索引值
【发布时间】:2016-12-25 22:18:46
【问题描述】:

所以我有一个 JSON 字符串,我从 AJAX 调用传递到我的控制器。我有一个要传递给动态对象的索引值列表。

我用

反序列化 JSON
JsonConvert.DeserializeObject<dynamic>(s)

这是该动态对象的输出:

"RolePermissions[0].RolePermissionId": "269",
 "RolePermissions[0].HasAccess": "false",
 "RolePermissions[1].RolePermissionId": "270",
 "RolePermissions[1].HasAccess": "false",
 "RolePermissions[2].RolePermissionId": "271",
 "RolePermissions[2].HasAccess": "true",
 "RolePermissions[3].RolePermissionId": "272",
 "RolePermissions[3].HasAccess": "false"

当我尝试使用

访问对象的 a 属性时
ssObj.RolePermissions[0].RolePermissionId 

我得到一个 RuntimeBinderException。我尝试使用 JObject.Parse,效果很好,但由于某种原因,数组中的值变得乱序。

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 请分享您尝试反序列化的s 的值。

标签: c# asp.net json serialization dynamic


【解决方案1】:

当您尝试执行RolePermissions[0].RolePermissionId 时,您正在尝试访问一个嵌套集合,该集合包含一个在索引0 处具有RolePermissionId 属性的对象。但是您的JSON 并不代表对象的层次结构,它代表一个单一的平面对象具有键/值对,其键包含句点和括号。由于 c# 标识符不允许此类字符,因此您无法直接使用 dynamic 访问此类属性值。

相反,您的选择包括:

  1. 利用JsonConvert.DeserializeObject&lt;dynamic&gt;(s) 实际上返回一个JObject 并使用它的dictionary indexer这一事实:

    var ssObj = JsonConvert.DeserializeObject<dynamic>(s);
    var rolePermissionId = (string)ssObj["RolePermissions[0].RolePermissionId"];
    
  2. 如果您更喜欢类型更多的解决方案,您可以反序列化为Dictionary&lt;string, dynamic&gt;

    var ssDict = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(s);
    var rolePermissionId = (string)ssDict["RolePermissions[0].RolePermissionId"];
    
  3. 或者对于更静态类型的解决方案,显式解析为 JObject 并使用 LINQ to JSON

    var jObj = JObject.Parse(s);
    var rolePermissionId = (string)jObj["RolePermissions[0].RolePermissionId"];
    

示例fiddle 显示了各种选项。

【讨论】:

  • 非常感谢!这样一个简单易行的解决方案,很容易循环。所有选项都很棒,非常感谢!我不能投票,因为我没有足够高的声誉,但我将其标记为已接受的答案。再次感谢!
【解决方案2】:

如果您可以控制通过 AJAX 发送的数据,请确保发送的数据格式正确。

为了能够反序列化变量s 比如:

var ssObj = JsonConvert.DeserializeObject<dynamic>(s);

并以这种方式访问​​生成的对象:

ssObj.RolePermissions[0].RolePermissionId

然后s 中的 JSON 值,根据您的示例和所需的行为,必须如下所示:

{
    "RolePermissions": [
        {
            "RolePermissionId": "269",
            "HasAccess": "false"
        },
        {
            "RolePermissionId": "270",
            "HasAccess": "false"
        },
        {
            "RolePermissionId": "271",
            "HasAccess": "true"
        },
        {
            "RolePermissionId": "272",
            "HasAccess": "false"
        }
    ]
}

这个快速单元测试表明,在将 JSON 反序列化为动态对象时可以获得索引值

[TestClass]
public class UnitTest1 {
    [TestMethod]
    public void GetIndexedValuesWhenDeserializingJSONIntoDynamicObject() {

        var s = @"
        {
            'RolePermissions': [
                {
                    'RolePermissionId': '269',
                    'HasAccess': 'false'
                },
                {
                    'RolePermissionId': '270',
                    'HasAccess': 'false'
                },
                {
                    'RolePermissionId': '271',
                    'HasAccess': 'true'
                },
                {
                    'RolePermissionId': '272',
                    'HasAccess': 'false'
                }
            ]
        }
        ";

        var ssObj = JsonConvert.DeserializeObject<dynamic>(s);

        var result = ssObj.RolePermissions[0].RolePermissionId;

        Assert.AreEqual("269", (string)result);
    }
}

因此,您需要确保向控制器发送格式正确的 JSON 以实现所需的行为。

【讨论】:

  • 感谢您的回答! @dbc 给出的答案是我想要的更多,但我很感激这个答案!
猜你喜欢
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 2015-03-17
相关资源
最近更新 更多