问题背景
问题需要定义一个类型接收HTTP请求的响应值,HttpResponse为json格式,有固定的 success,code,message,path
四个数据项分别是bool,int,string,string
类型。但是当success
值为true
时,会有具体结果data
字段返回,这个data
就复杂了,通常是一个类型的实例。
问题描述
问题是:如何设计,能灵活接收不同data类型的数据,使用NewtonSoft.json解析生成对应的对象?
尝试1
首先想到的是使用泛型了,根据不同的请求返回的data类型在使用的时候再传入具体的类型。
//定义response“模板”
public class Response<T>
{
public int code { get; set; }
public string message { get; set; }
public string path { get; set; }
public T data { get; set; }
}
//定义类型1
public class Mydata1
{
public string name { get; set; }
public int id { get; set; }
}
//定义类型2
public class Mydata2
{
public string color{ get; set; }
public int size { get; set; }
}
//使用
//data是json字符串
var response1 = JsonHelper.DeserializeAnonymousType(data, new Response<Mydata1>());
var response2 = JsonHelper.DeserializeAnonymousType(data, new Response<Mydata2>());
if (response1.success)
Mydata1 data1 = response1.data;
Console.Write(data1.name);
else
string errorMessage = response1.message;
if (response2.success)
Mydata1 data2 = response2.data;
Console.Write(data2.color);
else
string errorMessage = response2.message;
这样写固然可以满足要求了,但是注意到response.success
为false
时实际上是一个异常请求,所以在前端希望能用抛出异常的形式来处理。但是这就存在一个问题,当response.success
为false
时,是没有data
项的,而在调用Response类时是传入了data类型的,这样就无法统一处理response.success = false
时的结果。与是有了尝试2
尝试2
注意到,每次请求返回值中只有data
类型不确定,而其余四项是确定的类型,所有考虑设计一个类型包含确定的四项,而让Response
继承这个类型,再在Response
中实现data
。
//定义基类
public class ResponseBase
{
public int code { get; set; }
public string message { get; set; }
public string path { get; set; }
}
//定义Response
public class Response<T>:ResponseBase
{
public T data { get; set; }
}
//定义一个HTTP请求异常的类
public class HttpRequestException : Exception
{
public bool success { get; }
public int code { get; }
public override string Message { get; }
public string path { get; }
public HttpRequestException(ResponseBase response)
{
this.code = response.code;
this.success = response.success;
this.path = response.path;
this.Message = response.message;
}
}
//使用
public static Mydata1 GetMydata1()
{
//这里省略了获取http请求结果的代码,得到json字符串data
var response = sonHelper.DeserializeAnonymousType(data, new Response<MyData1>());
if (response.success)
return response.data;
else
throw new HttpRequestException(response);
}
//捕获异常
try
{
var data1 = GetMydata1();
}
catch (HttpRequestException ex)
{
Console.Writeline(ex.Message);
}
总结
使用泛型来解决不确定的传入类型,使用继承实现公共部分的定义方便类型间的转化。