【问题标题】:Unable to access dynamic property无法访问动态属性
【发布时间】:2016-04-10 17:49:38
【问题描述】:

我有一个dynamic 对象,但我无法访问它的属性。

为了便于阅读,我修改了下面的代码。

我正在使用包:Newtonsoft.Json.8.0.1\lib\net45\Newtonsoft.Json.dll

我正在尝试在下面的代码中读取对象mDevice

代码

foreach (dynamic mDevice in dynamicList.mobile_devices)
{
    MobileDevice mobileDevice = new MobileDevice() //====> Throws Exception
    {
        Id = mDevice.id,
        Name = mDevice.name
    };
}

Exception 如下:

“Newtonsoft.Json.Linq.JProperty”不包含“id”的定义

如果我在Exception 发生之前使用我的Watch Window 输出mDevice,我会得到以下结果:

谁能解释我为什么无法访问这些属性?

更新
dynamicList 来源:

IGNORE我将 XML 转换为 JSON 的原因还有其他不相关的目的

string MobileDevicesInJSON = JsonConvert.SerializeXmlNode(doc);
dynamic dynamicList = JsonConvert.DeserializeObject(MobileDevicesInJSON);



原始 JSON:

{"?xml":{"@version":"1.0","@encoding":"UTF-8"},"mobile_device_application":{"general":{"id":"5","name":"Acta Dome Calculator - Free","display_name":"Acta Dome Calculator - Free","description":null,"bundle_id":"com.itwcalculator.calculatorforipadfree","version":"3.1.1","internal_app":"true","category":{"id":"-1","name":"No category assigned"},"ipa":{"name":null,"uri":null,"data":null},"icon":null,"mobile_device_provisioning_profile":null,"url":{"@deprecated":"9.4","#text":"https://itunes.apple.com/nl/app/calculator-free/id398129933?mt=8&uo=4"},"itunes_store_url":"https://itunes.apple.com/nl/app/calculator-free/id398129933?mt=8&uo=4","deployment_type":"Install Automatically/Prompt Users to Install","deploy_automatically":"true","deploy_as_managed_app":"true","remove_app_when_mdm_profile_is_removed":"false","prevent_backup_of_app_data":"false","keep_description_and_icon_up_to_date":"false","free":"true","take_over_management":"false","host_externally":"true","external_url":"https://itunes.apple.com/nl/app/calculator-free/id398129933?mt=8&uo=4","site":{"id":"1","name":"Acta Dome"}},"scope":{"all_mobile_devices":"false","all_jss_users":"false","mobile_devices":{"mobile_device":{"id":"9","name":"iPad R&D 01S","udid":"dd1dff5d598e3fce0b4b16288f0b9bf1551d0eb2","wifi_mac_address":"9C:35:EB:53:00:84"}},"mobile_device_groups":{"mobile_device_group":{"id":"9","name":"Acta Dome Unassigned"}},"buildings":null,"departments":null,"jss_users":{"user":[{"id":"9","name":"ACTA_Astrid"},{"id":"7","name":"ACTA_RenD01"}]},"jss_user_groups":{"user_group":{"id":"7","name":"Acta Dome StudentGroup 01"}},"limit_to_users":{"user_groups":null},"network_limitations":{"any_ip_address":"true","network_segments":null},"limitations":{"users":null,"user_groups":null,"network_segments":null},"exclusions":{"mobile_devices":null,"mobile_device_groups":null,"buildings":null,"departments":null,"jss_users":null,"jss_user_groups":null,"users":null,"user_groups":null,"network_segments":null}},"self_service":{"self_service_description":null,"self_service_icon":null,"feature_on_main_page":"false","self_service_categories":null}}}

【问题讨论】:

  • 循环内mDevice的实际类型是什么,是JProperty吗?
  • 也许你应该访问mDevice.mobile_device.id
  • 在 Locals 或 Watch 窗口中展开 mDevice 变量,看看里面有什么。立即窗口不利于显示结构。
  • @NickProzee:给我们一些 JSON 来重现问题。几乎可以肯定,问题是反序列化没有完成您的预期,但是如果没有可测试的可重现版本的错误,很难确定您的问题出在哪里。我试图自己重现你的问题,它对我来说很好,所以它很难帮助......
  • 我为需要的人添加了原始 JSON

标签: c# .net json linq


【解决方案1】:

如果您查看 Watch 窗口中的 Type 列(您的帖子中尚未完全显示,并且它包含非常重要的信息),您会看到 mDevice 的类型是 Newtonsoft.Json.Linq.JProperty (顺便说一句,异常消息也暗示了这一点)而不是您期望的Newtonsoft.Json.Linq.JObject。这反过来意味着dynamicList.mobile_devices 不是您期望的Newtonsoft.Json.Linq.JArray,实际上它是Newtonsoft.Json.Linq.JObject 实例。所以整个逻辑是错误的。这是一个基于帖子中“原始 JSON”的工作示例:

string originalJSON = ...;
dynamic root = JsonConvert.DeserializeObject(originalJSON);
dynamic mobileDevices = root.mobile_device_application.scope.mobile_devices;
dynamic mobileDevice = mobileDevices.mobile_device;
var id = (int)mobileDevice.id;
var name = (string)mobileDevice.name;

或者

foreach (var item in mobileDevices)
{
    dynamic mobileDevice = item.Value;
    var id = (int)mobileDevice.id;
    var name = (string)mobileDevice.name;
}

作为一般建议,开始使用 Locals/Watch 窗口功能而不是值。例如,有一个叫做“动态视图”的东西出现在具有动态支持的扩展对象的底部,在这种情况下显示:

【讨论】:

  • 感谢您简短而明确的回答,这解释了出了什么问题!
【解决方案2】:

这里的动态对象是一个字典(键值对),其中“mobile_device”是一个键,对应的包含id,name等的对象就是这个键的值。

您应该能够使用 mobile_device 作为 mDevice 上的键来访问它,例如 mDevice["mobile_device"]。这应该会返回一个对象,该对象再次具有键值对(id 键和 9 是值,name 键和 ipad em> 是价值....)。再次对返回的对象使用相同的语法(键/值)来获取对应的值。

【讨论】:

  • 尝试访问 mDevice["mobile_device"] 或 mDevice["mobile_device"].Key 会引发异常:无法访问 Newtonsoft.Json.Linq.JProperty 上的子值。
【解决方案3】:

查看对象,更改为应该可以工作的代码:

    Id = mDevice.mobile_device.id,
    Name = mDevice.mobile_device.name

这在您的观察窗口中很清楚。


我没有看到任何名为 mobile_devices 的东西——你是说 mobile_device 吗?

您显示的代码不应迭代循环,因为该属性名称不应该存在。

【讨论】:

  • 是的,因为 dynamicList.mobile_devices 是“mobile_device”的列表。我在上面的代码中省略了那个,因为它不相关,我的范围是'mDevice'
【解决方案4】:

这可能是一个解决方案。

foreach (dynamic mDevice in dynamicList)
{
    object mDeviceProperties = mDevice.Value;

    var mobileDevice = JsonConvert.DeserializeObject<MobileDevice>(mDeviceProperties.ToString());
}

【讨论】:

  • 问题是:谁能解释我为什么无法访问这些属性?请看一下@Ivan Stoev 信息丰富的答案应该是什么样子......
  • 您只是将 mDevice 反序列化为对象,这就是您无法访问属性的原因。 mDevice 必须反序列化为 MobileDevice 然后才能访问属性。希望这至少部分回答了您的问题。
猜你喜欢
  • 2021-11-09
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 2017-09-30
  • 1970-01-01
  • 2020-11-08
  • 1970-01-01
相关资源
最近更新 更多