WebApi接口 - 响应输出xml和json


格式化数据这东西,主要看需要的运用场景,今天和大家分享的是webapi格式化数据,这里面的例子主要是输出json和xml的格式数据,测试用例很接近实际常用情况;希望大家喜欢,也希望各位多多扫码支持和点赞谢谢:

. 自定义一个Action,响应输出集合数据

. api返回json数据的两种方式

. json时间格式处理方式

. 让api接口支持返回json和xml数据

下面一步一个脚印的来分享:

. 自定义一个Action,响应输出集合数据

首先,我们新建一个webapi项目,新建好以后我们能够找到 Controllers/ValuesController.cs 文件,查看里面有自动生成的一些代码,我们先不管;然后我们创建一个学生 MoStudent

1 public class MoStudent
2 {
3 public DateTime Birthday { get; set; }
4
5 public int Id { get; set; }
6
7 public string Name { get; set; }
8
9 public bool Sex { get; set; }
11

然后我们在 ValuesController

1  public List<MoStudent> students = new List<MoStudent>() { 
2
3 new MoStudent{ Id =1 , Name ="小1", Sex = true, Birthday= Convert.ToDateTime("1991-05-31")},
4 new MoStudent{ Id =2 , Name ="小2", Sex = false, Birthday= Convert.ToDateTime("1991-05-31")},
5 new MoStudent{ Id =3 , Name ="小3", Sex = false, Birthday= Convert.ToDateTime("1991-05-31")},
6 new MoStudent{ Id =4 , Name ="小4", Sex = true, Birthday= Convert.ToDateTime("1991-05-31")}
7

再来,我们新创建一个 GetAllStudents01()

1  public List<MoStudent> GetAllStudents01()
2 {
3 return students;
4

这个时候我们生成一下项目,然后在浏览器访问下地址为: http://localhost:1001/api/values

这个错误信息是该地址同时匹配上了两个api的Action,分别为 Get()和GetAllStudents01() 两个方法,这种错误我们应该怎么处理呢;一种可以删除其中一个方法;二种方式是在默认路由设置下Action,然后通过具体的Controller/Action地址来访问;三种是通过Route修改下对应的访问路由(这种方法前面一篇文章已经有说明);这里我们就使用第二种,先来修改下 WebApiConfig.cs

1 config.Routes.MapHttpRoute(
2 name: "DefaultApi",
3 routeTemplate: "api/{controller}/{action}/{id}",
4 defaults: new { id = RouteParameter.Optional }
5

生成后,我们在浏览器中这样访问: http://localhost:1001/api/values/GetAllStudents01

webapi能正常返回数据了,但是地址感觉好长的样子,不利于我们测试,那么下么我们使用上一篇文章用到的标记RoutePrefix和Route来变动下路由,增加的代码如:

然后我们测试访问下该地址: http://localhost:1001/s/all01

 

. api返回json数据的两种方式

Student 属性全部展示了出来,我们真实开发接口的时候,通常会有些对象的属性不会展示,下面我们通过增加 DataContract 和 DataMember

1 [DataContract]
2 public class MoStudent
3 {
4 [DataMember]
5 public DateTime Birthday { get; set; }
6
7 [DataMember]
8 public int Id { get; set; }
9
10 [DataMember]
11 public string Name { get; set; }
12
13 [DataMember]
14 public bool Sex { get; set; }
15
16

然后咋们运行下程序,在页面看到的结果信息和之前的结果一模一样:

下面把 Birthday 属性上面的 DataMember

可以看到输出的结果中已经没有了这个 Birthday ,这里能看出的结果是如果未标记 DataMember

1 [DataContract]
2 public class MoStudent
3 {
4 [DataMember(Order = 3)]
5 public DateTime Birthday { get; set; }
6
7 [DataMember(Order = 0)]
8 public int Id { get; set; }
9
10 [DataMember(Order = 1)]
11 public string Name { get; set; }
12
13 [DataMember(Order = 2)]
14 public bool Sex { get; set; }
15
16

然后咋们再运行起来看效果图:

相信仔细的朋友能够发现,此时Birthday数据暂时的位置已经从第一个变到了最后一个,没错这就是DataMember中Order属性参数的效果:用来指定显示输出数据的位置;

好了咋们来看正题,webapi返回json数据这里讲解两种,一种是使用自带的Json格式化方式,使用方法只需要在 Global.asax.cs

在全局设置中,把所有返回的格式清除,设置JSON。所有的返回的xml格式都会被清除

在WebApiConfig类的Register方法中,我们添加下面代码:

config.Formatters.Clear();
config.Formatters.Add(new


因为webapi在启动的时候,默认格式化数据有两种方式xml和json,而xml是其默认的启动方式,所以这里是需要清除了xml格式化,那么另外只剩下json,所以咋们在运行程序后能看到这样的结果输出:

结果返回了json数据,如果咋们想要如上面xml一样吧Birthday隐藏掉,我们同样也可以使用 DataContract 和 DataMember 来做这效果,删除Birthday对应的 DataMember

同理,我们把Birthday的DataMember还原,然后指定Order属性值 [DataMember(Order=1)]

好了这试第一种json格式化的方式,下面来看下用使用Json.Net怎么来格式化,为了避免影响效果,我们把 Global.asax.cs

1 [Route("all01_1")]
2 public async Task<HttpResponseMessage> GetAllStudents01_1()
3 {
4 var result = await JsonConvert.SerializeObjectAsync(students);
5
6 return new HttpResponseMessage
7 {
8 Content = new StringContent(result),
9 StatusCode = HttpStatusCode.OK
10 };
11

这里用到了Json.Net的 JsonConvert.SerializeObjectAsync 方法来格式化成字符串,然后传递给 HttpResponseMessage ,最终输出的效果和上面一样,好了咋们也来看看这种方式怎么来隐藏不希望接口暴露的属性,这里我们用 JsonIgnore

1 [JsonIgnore]
2 public DateTime Birthday { get; set; }

然后运行看一下效果:

我们再来看一下怎么来设置属性的排序,可以使用 JsonProperty(Order = 1)

1 public class MoStudent
2 {
3 //[DataMember(Order = 1)]
4 [JsonProperty(Order = 1)]
5 public DateTime Birthday { get; set; }
6
7 //[DataMember(Order = 0)]
8 [JsonProperty(Order = 0)]
9 public int Id { get; set; }
10
11 //[DataMember(Order = 1)]
12 [JsonProperty(Order = 1)]
13 public string Name { get; set; }
14
15 //[DataMember(Order = 2)]
16 [JsonProperty(Order = 2)]
17 public bool Sex { get; set; }
18
19

能得到和DataMember设置的一样的结果:

 

. json时间格式处理方式

要说时间格式化,我们通常的生日格式如:yyyy-MM-dd这样,下面也分别对刚才上面两种json化出来的时间做格式化;先来看Json.net,我们先来定义一个名称为 SelfDateTimeFormat 的类并且继承 DateTimeConverterBase 类,然后需要重写 ReadJson和WriteJson

1  /// <summary>
2 /// 自定义时间格式化
3 /// </summary>
4 public class SelfDateTimeFormat : DateTimeConverterBase
5 {
6 public IsoDateTimeConverter TimeConvert = null;
7
8 public SelfDateTimeFormat() {
9
10 TimeConvert = new IsoDateTimeConverter
11 {
12 DateTimeFormat = "yyyy-MM-dd"
13 };
14 }
15
16 public SelfDateTimeFormat(string formatter = "yyyy-MM-dd HH:mm:ss")
17 {
18
19 TimeConvert = new IsoDateTimeConverter
20 {
21 DateTimeFormat = formatter
22 };
23 }
24
25 public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
26 {
27
28 return TimeConvert.ReadJson(reader, objectType, existingValue, serializer);
29 }
30
31 public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
32 {
33
34 TimeConvert.WriteJson(writer, value, serializer);
35 }
36

然后我们需要在实体类的时间属性上增加这样的标记: [JsonConverter(typeof(OverridClass.SelfDateTimeFormat))] ,这里的 SelfDateTimeFormat

好了,咋们再来看webapi自带的json格式化如何定义一个日期格式的数据,我们需要在Global.asax.cs中增加如下代码:

1 var format = GlobalConfiguration.Configuration.Formatters;
2 format.JsonFormatter.SerializerSettings.DateFormatString = "yyyy.MM.dd";

没错,只需要如此简单的代码,即可时间格式化成:

 

. 让api接口支持返回json和xml数据

开篇第一小节已经有简单说明webapi有自己的json和xml格式化处理,这里们来设置通过参数请求返回不同的数据格式;首先还是需要在Global中设置如下代码:

1  var format = GlobalConfiguration.Configuration.Formatters;
2 format.JsonFormatter.SerializerSettings.DateFormatString = "yyyy.MM.dd";
3
4 //清除默认xml
5 format.XmlFormatter.SupportedMediaTypes.Clear();
6
7 //通过参数设置返回格式
8 format.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("t", "json", "application/json"));
9 format.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("t", "xml", "application/xml"));

这里用到了 QueryStringMapping 类,并传递给他构造函数的参数 new QueryStringMapping("t","json", "application/json") 和 new QueryStringMapping("t", "xml", "application/xml")

​http://localhost:1001/s/all01?t=xml​

 

​http://localhost:1001/s/all01?t=json​