将 ExpandoObject 反序列化为对象
Deserialize an ExpandoObject into Object
我有一个将与多个客户端一起使用的对象。该对象具有一组在所有客户端中通用的固定属性。这是一个对象可能看起来像的示例:
public class Applicant
{
public string ApplicantId { get; set; }
public string ProducerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
...
public List<dynamic> Information { get; set; }
}
我们将通过 Web API POST 接收此信息。所以我有这个控制器签名:
[HttpPost]
public void Post([FromBody] dynamic value)
{
var converter = new ExpandoObjectConverter();
dynamic input = JsonConvert.DeserializeObject<Loan>(value,converter);
}
但是当我 运行 这段代码时,NewtonSoft 一直给我错误
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject<ExpandoObjectTestAPI.Models.Loan>(string, params Newtonsoft.Json.JsonConverter[])' has some invalid arguments'
环顾四周似乎传入的动态类型有问题。那么我如何传入这个 JSON 以便我可以使用 ExpandoObjectConverter 解析它?
该框架非常擅长序列化和反序列化。如果您已经知道正在传递的模型,则没有理由使用动态。所以你应该简单地这样做:
[HttpPost]
public IActionResult Post([FromBody] Loan value)
{
// Loan is already instantiated with your data. You can use the object now.
return Ok(value); // <-- for example
}
谈到在你的模型中有 dynamic
个对象:
我不能代表微软对 JSON 的实施,但 Newtonsoft.Json
处理得很好。假设您的 Loan
模型如下所示:
public sealed class Loan
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("myDynamicStuff")]
public dynamic MyDynamicStuff { get; set; }
}
上面的控制器代码不需要任何额外的努力就可以很好地反序列化。
这并没有回答使用动态的问题,但值得考虑通过使用字典来代替自定义属性来避免这种情况。以下适用于通用 key/value 对:
public class Applicant
{
...Standard properties
public IDictionary<string, object> Custom { get; set; }
}
它将接受 JSON 以及嵌套在您的“自定义”命名空间下的任意动态字段:
{
"applicationId": "123",
"producerId": "456",
"custom": {
"favoriteAnimal": "turtles",
"someRandomMetadata": 42,
"someUnforeseenList": ["foo", "bar"]
}
}
我以这种方式处理 user-defined 扩展字段时运气不错。它还具有将自定义字段隔离到嵌套命名空间以与 built-in 数据隔离的有争议的优势。
我有一个将与多个客户端一起使用的对象。该对象具有一组在所有客户端中通用的固定属性。这是一个对象可能看起来像的示例:
public class Applicant
{
public string ApplicantId { get; set; }
public string ProducerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
...
public List<dynamic> Information { get; set; }
}
我们将通过 Web API POST 接收此信息。所以我有这个控制器签名:
[HttpPost]
public void Post([FromBody] dynamic value)
{
var converter = new ExpandoObjectConverter();
dynamic input = JsonConvert.DeserializeObject<Loan>(value,converter);
}
但是当我 运行 这段代码时,NewtonSoft 一直给我错误
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject<ExpandoObjectTestAPI.Models.Loan>(string, params Newtonsoft.Json.JsonConverter[])' has some invalid arguments'
环顾四周似乎传入的动态类型有问题。那么我如何传入这个 JSON 以便我可以使用 ExpandoObjectConverter 解析它?
该框架非常擅长序列化和反序列化。如果您已经知道正在传递的模型,则没有理由使用动态。所以你应该简单地这样做:
[HttpPost]
public IActionResult Post([FromBody] Loan value)
{
// Loan is already instantiated with your data. You can use the object now.
return Ok(value); // <-- for example
}
谈到在你的模型中有 dynamic
个对象:
我不能代表微软对 JSON 的实施,但 Newtonsoft.Json
处理得很好。假设您的 Loan
模型如下所示:
public sealed class Loan
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("myDynamicStuff")]
public dynamic MyDynamicStuff { get; set; }
}
上面的控制器代码不需要任何额外的努力就可以很好地反序列化。
这并没有回答使用动态的问题,但值得考虑通过使用字典来代替自定义属性来避免这种情况。以下适用于通用 key/value 对:
public class Applicant
{
...Standard properties
public IDictionary<string, object> Custom { get; set; }
}
它将接受 JSON 以及嵌套在您的“自定义”命名空间下的任意动态字段:
{
"applicationId": "123",
"producerId": "456",
"custom": {
"favoriteAnimal": "turtles",
"someRandomMetadata": 42,
"someUnforeseenList": ["foo", "bar"]
}
}
我以这种方式处理 user-defined 扩展字段时运气不错。它还具有将自定义字段隔离到嵌套命名空间以与 built-in 数据隔离的有争议的优势。