在POCO中处理不同类型的属性



我通常从API 收到一个json响应

{
"errors": "Error message"
}

我的问题是,同一个api可以用另一种格式返回一些其他响应:

{
"errors": [
{ "message": "error message 1", "description": "error description 1" },
{ "message": "error message 2", "description": "error description 2" }
]
}

我的问题是,我必须反序列化这个响应并将其映射到一个对象,以便以某种格式返回它。

namespace namespace.models
{
public class ErrorResponse
{
[JsonProperty(PropertyName = "errors")]
public ErrorDetail[] Errors { get; set; }
}
}

我使用以下代码来处理帖子请求:

using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); 
HttpContent content = new StringContent(
JsonConvert.SerializeObject(request), 
Encoding.UTF8, 
"application/json");
HttpResponseMessage httpResponse = await client.PostAsync(url, content);
string output = await httpResponse.Content.ReadAsStringAsync();

PostResponse returnValue = new PostResponse ();
if (httpResponse.StatusCode == (HttpStatusCode)201)
{
returnValue.Id = Int32.Parse(output);
}
else
{
ErrorResponse response = JsonConvert.DeserializeObject<ErrorResponse>(output)
throw new Exception(httpResponse.ReasonPhrase + " " + output);
}
return returnValue;

}

我的问题是,我不知道如何处理可以是字符串的响应,然后我的异常应该是";输出";我收到的,或者一个对象数组。我也应该把它作为字符串返回吗?或者有没有办法以不同的方式处理回复?

不幸的是,在这里使用JsonConvert.DeserializeObject无法轻松进行反序列化。这可以用自定义转换器完成,但对我来说,这太麻烦了。

幸运的是,您可以很容易地将响应解析为JObject,然后检查JToken的类型并将其转换为所需的类型,如

var json1 = "{rn  "errors": "Error message"rn}";
var json2 = "{rn  "errors": [rn     { "message": "error message 1", "description": "error description 1" },rn     { "message": "error message 2", "description": "error description 2" }rn  ]rn}";
var jo = JObject.Parse(json2);
var errResponse = new ErrorResponse();
if (jo["errors"] is JArray array)
{
errResponse.Errors = array.ToObject<ErrorDetail[]>() ?? Array.Empty<ErrorDetail>();
}
else
{
errResponse.Errors = new[] { new ErrorDetail() { Message = jo["errors"]?.Value<string>() ?? string.Empty } };
}
我创建了两个类并使用try-catch。一个是将成员error声明为字符串,另一个是对象数组。
public static void Main(string[] args)
{
var json1 = "{rn  "errors": "Error message"rn}";
var json2 = "{rn  "errors": [rn     { "message": "error message 1", "description": "error description 1" },rn     { "message": "error message 2", "description": "error description 2" }rn  ]rn}";
try
{
ErrorsResponse response = 
JsonConvert.DeserializeObject<ErrorsResponse>(json1);
Console.WriteLine(response.ToString());
}
catch (Exception e)
{
ErrorResponse response = 
JsonConvert.DeserializeObject<ErrorResponse>(json1);
Console.WriteLine(response.ToString());
}
}

我没有尝试其他解决方案。我要测试一下。

尝试这个


string output = await httpResponse.Content.ReadAsStringAsync();

if (httpResponse.StatusCode == (HttpStatusCode)201)
{
returnValue.Id = Int32.Parse(output);
}
else
{
var jsonObject = JObject.Parse(output);
var errorResponse = jsonObject["errors"].GetType().Name == "JArray" ? 
jsonObject2.ToObject<ErrorResponse>() :
new ErrorResponse { Errors = new ErrorDetail[] 
{ new ErrorDetail { Message = (string)jsonObject["errors"], Description="Short error format" } } };

throw new Exception(httpResponse.ReasonPhrase + "  " 
+ string.Join("; rn", errorResponse.Errors.Select(i=> "Message: "+ i.Message 
+ " Description: "+i.Description)); );
}
return returnValue;

或者你也可以使用这个代码

public class ErrorResponse
{
[JsonProperty("errors")]
public ErrorDetail[] Errors { get; set; }
}

public partial class ErrorDetail
{
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
}

最新更新