反序列化Web Api OData响应
本文关键字:响应 OData Api Web 反序列化 | 更新日期: 2023-09-27 18:16:46
我有一个OData V4控制器返回的实体框架对象。我返回一个IQueryable,如果我调用没有任何OData子句的OData端点,我可以成功地做到这一点:
var content = response.Content.ReadAsAsync<IQueryable<Person>>();
JSON格式的响应如下:
{
"@odata.context":"http://xxx:8082/odata/$metadata#Persons","value":[
{
"Id":"291b9f1c-2587-4a35-993e-00033a81f6d5",
"Active":true,
"Alert":"Some alerts for the Person",
"Comments":"Some comments for the Person"
}
]
}
但是一旦我开始使用OData,例如通过在Complex属性上使用$expand,我就会得到以下异常:
无法将当前JSON对象(例如{"name":"value"})反序列化为类型'System.Linq.IQueryable ' 1[xxx. xxx]。
,因为该类型需要一个JSON数组(例如[1,2,3])来正确反序列化。响应如下:
{
"@odata.context":"http://aqavnext01:8082/odata/$metadata#Persons","value":[
{
"Id":"291b9f1c-2587-4a35-993e-00033a81f6d5",
"Active":true,
"Alert":"Some alerts for the Person",
"Comments":"Some comments for the Person",
"Party":{
"Id":"291b9f1c-2587-4a35-993e-00033a81f6d5"
}
}
]
}
我正在使用我的Web Api返回的相同对象进行反序列化,所以我不明白为什么它失败了。同样的问题,当我应用$select.
尝试像这样反序列化内容:
var content = response.Content.ReadAsAsync<ODataResponse<Person>>();
其中odatresponse为:
internal class ODataResponse<T>
{
public T[] Value { get; set; }
}
如果需要访问响应JSON中的@odata.xxx
字段(例如实现分页结果的循环),下面是我的实现,它扩展了andygjp的解决方案。
我使用RestSharp作为我的HTTP客户端和Json。. NET用于(反)序列化。步骤如下:
实现使用Json的自定义IRestSerializer
。. NET来替换默认的RestSharp序列化器。下面的示例实现:
public class JsonNetSerializer : IRestSerializer
{
private readonly JsonSerializerSettings _settings;
public JsonNetSerializer()
{
_settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
_settings.Converters.Add(new StringEnumConverter());
}
public string Serialize(Parameter parameter) => JsonConvert.SerializeObject(parameter.Value, Formatting.None, _settings);
public string Serialize(object obj) => JsonConvert.SerializeObject(obj, Formatting.None, _settings);
public T Deserialize<T>(IRestResponse response) => JsonConvert.DeserializeObject<T>(response.Content);
public string[] SupportedContentTypes => new string[] { "application/json", "text/json", "text/x-json", "text/javascript", "*+json" };
public DataFormat DataFormat => DataFormat.Json;
public string ContentType { get; set; } = "application/json";
}
接下来,定义一个表示OData响应的类。我的扩展响应类(包括@odata.nextLink
字段)如下所示。
private class ODataResponse<T>
{
public T[] Value { get; set; }
[JsonProperty("@odata.nextLink")]
public string NextLink { get; set; }
}
最后,创建RestClient
的一个实例,设置前面创建的自定义序列化器:
var client = new RestClient("https://base.url.here/")
.UseSerializer(() => new JsonNetSerializer());
现在,当我执行请求时,响应对象对象中的数据也包含我的OData值。
var response = await client.ExecuteAsync<T>(request);
var nextLink = response.Data.NextLink;
我确信这可以使用标准的HttpClient
而不是RestSharp来完成,因为真正的工作是由序列化器完成的。这只是我手头的示例实现。