ABP入门系列之Json格式化
讲完了分页功能,这一节我们先不急着实现新的功能。来简要介绍下abp中json的用法。为什么要在这一节讲呢?当然是做铺垫啊,后面的系列文章会经常和json这个东西打交道。
一、json是干什么的
json(javascript object notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。json采用完全独立于语言的文本格式,但是也使用了类似于c语言家族的习惯(包括c, c++, c#, java, javascript, perl, python等)。 这些特性使json成为理想的数据交换语言。
json一般用于表示:
名称/值对:
{"firstname":"brett","lastname":"mclaughlin","email":"aaaa"}
数组:
{ "people":[ {"firstname":"brett","lastname":"mclaughlin","email":"aaaa"}, {"firstname":"jason","lastname":"hunter","email":"bbbb"}, {"firstname":"elliotte","lastname":"harold","email":"cccc"} ] }
二、asp.net mvc中的jsonresult
asp.net mvc中默认提供了jsonresult来处理需要返回json格式数据的情况。
一般我们可以这样使用:
public actionresult movies() { var movies = new list<object>(); movies.add(new { title = "ghostbusters", genre = "comedy", releasedate = new datetime(2017,1,1) }); movies.add(new { title = "gone with wind", genre = "drama", releasedate = new datetime(2017, 1, 3) }); movies.add(new { title = "star wars", genre = "science fiction", releasedate = new datetime(2017, 1, 23) }); return json(movies, jsonrequestbehavior.allowget); }
其中json()是controller基类中提供的虚方法。
返回的json结果格式化后为:
[ { "title": "ghostbusters", "genre": "comedy", "releasedate": "\/date(1483200000000)\/" }, { "title": "gone with wind", "genre": "drama", "releasedate": "\/date(1483372800000)\/" }, { "title": "star wars", "genre": "science fiction", "releasedate": "\/date(1485100800000)\/" } ]
仔细观察返回的json结果,有以下几点不足:
返回的字段大小写与代码中一致。这就要求我们在前端中也要与代码中用一致的大小写进行取值(item.title,item.genre,item.releasedate)。
不包含成功失败信息:如果我们要判断请求是否成功,我们要手动通过获取json数据包的length获取。
返回的日期未格式化,在前端还需自行格式化输出。
三、abp中对json的封装
所以abp封装了abpjsonresult继承于jsonresult,其中主要添加了两个属性:
camelcase:大小驼峰(默认为true,即小驼峰格式)
indented :是否缩进(默认为false,即未格式化)
并在abpcontroller中重载了controller的json()方法,强制所有返回的json格式数据为abpjsonresult类型,并提供了abpjson()的虚方法。
/// <summary> /// json the specified data, contenttype, contentencoding and behavior. /// </summary> /// <param name="data">data.</param> /// <param name="contenttype">content type.</param> /// <param name="contentencoding">content encoding.</param> /// <param name="behavior">behavior.</param> protected override jsonresult json(object data, string contenttype, encoding contentencoding, jsonrequestbehavior behavior) { if (_wrapresultattribute != null && !_wrapresultattribute.wraponsuccess) { return base.json(data, contenttype, contentencoding, behavior); } return abpjson(data, contenttype, contentencoding, behavior); } protected virtual abpjsonresult abpjson( object data, string contenttype = null, encoding contentencoding = null, jsonrequestbehavior behavior = jsonrequestbehavior.denyget, bool wrapresult = true, bool camelcase = true, bool indented = false) { if (wrapresult) { if (data == null) { data = new ajaxresponse(); } else if (!(data is ajaxresponsebase)) { data = new ajaxresponse(data); } } return new abpjsonresult { data = data, contenttype = contenttype, contentencoding = contentencoding, jsonrequestbehavior = behavior, camelcase = camelcase, indented = indented }; }
在abp中用controler继承自abpcontroller,直接使用return json(),将返回json结果格式化后:
{ "result": [ { "title": "ghostbusters", "genre": "comedy", "releasedate": "2017-01-01t00:00:00" }, { "title": "gone with wind", "genre": "drama", "releasedate": "2017-01-03t00:00:00" }, { "title": "star wars", "genre": "science fiction", "releasedate": "2017-01-23t00:00:00" } ], "targeturl": null, "success": true, "error": null, "unauthorizedrequest": false, "__abp": true }
其中result为代码中指定返回的数据。其他几个键值对是abp封装的,包含了是否认证、是否成功、错误信息,以及目标url。这几个参数是不是很sweet。
也可以通过调用return abpjson()来指定参数进行json格式化输出。
仔细观察会发现日期格式还是怪怪的。2017-01-23t00:00:00,多了一个t。查看abpjsonreult源码发现调用的是newtonsoft.json序列化组件中的jsonconvert.serializeobject(obj, settings);进行序列化。
查看newtonsoft.json官网介绍,日期格式化输出,需要指定isodatetimeconverter的datetimeformat即可。
isodatetimeconverter timeformat = new isodatetimeconverter(); timeformat.datetimeformat = "yyyy-mm-dd hh:mm:ss"; jsonconvert.serializeobject(dt, formatting.indented, timeformat)
那在我们abp中我们怎么去指定这个datetimeformat呢?
abp中提供了abpdatetimeconverter类继承自isodatetimeconverter。
但查看abp中集成的json序列化扩展类:
public static class jsonextensions { /// <summary>converts given object to json string.</summary> /// <returns></returns> public static string tojsonstring(this object obj, bool camelcase = false, bool indented = false) { jsonserializersettings settings = new jsonserializersettings(); if (camelcase) settings.contractresolver = (icontractresolver) new camelcasepropertynamescontractresolver(); if (indented) settings.formatting = formatting.indented; settings.converters.insert(0, (jsonconverter) new abpdatetimeconverter()); return jsonconvert.serializeobject(obj, settings); } }
明显没有指定datetimeformat,那我们就只能自己动手了,具体代码请参考。
当有异常发生时,abp返回的json格式化输出以下结果:
{ "targeturl": null, "result": null, "success": false, "error": { "message": "an internal error occured during your request!", "details": "..." }, "unauthorizedrequest": false }
当不需要abp对json进行封装包裹怎么办?
简单。只需要在方法上标记[dontwrapresult]特性即可。这个特性其实是一个快捷方式用来告诉abp不要用abpjsonresult包裹我,看源码就明白了:
namespace abp.web.models { [attributeusage(attributetargets.class | attributetargets.interface | attributetargets.method)] public class dontwrapresultattribute : wrapresultattribute { /// <summary> /// initializes a new instance of the <see cref="dontwrapresultattribute"/> class. /// </summary> public dontwrapresultattribute() : base(false, false) { } } /// <summary> /// used to determine how abp should wrap response on the web layer. /// </summary> [attributeusage(attributetargets.class | attributetargets.interface | attributetargets.method)] public class wrapresultattribute : attribute { /// <summary> /// wrap result on success. /// </summary> public bool wraponsuccess { get; set; } /// <summary> /// wrap result on error. /// </summary> public bool wraponerror { get; set; } /// <summary> /// log errors. /// default: true. /// </summary> public bool logerror { get; set; } /// <summary> /// initializes a new instance of the <see cref="wrapresultattribute"/> class. /// </summary> /// <param name="wraponsuccess">wrap result on success.</param> /// <param name="wraponerror">wrap result on error.</param> public wrapresultattribute(bool wraponsuccess = true, bool wraponerror = true) { wraponsuccess = wraponsuccess; wraponerror = wraponerror; logerror = true; } } }
在abpresultfilter和abpexceptionfilter过滤器中会根据wrapresultattribute、dontwrapresultattribute特性进行相应的过滤。
四、json日期格式化
第一种办法:前端js转换:
//格式化显示json日期格式 function showdate(jsondate) { var date = new date(jsondate); var formatdate = date.todatestring(); return formatdate; }
第二种办法:在abp的wepapimodule(模块)中指定jsonformatter的时间序列化时间格式。
globalconfiguration.configuration.formatters.jsonformatter.serializersettings.dateformatstring ="yyyy-mm-dd hh:mm:ss";
ps:这种方法仅对webapi有效。
总结
本节主要讲解了以下几个问题:
asp.net中jsonresult的实现。
abp对jsonresult的再封装,支持指定大小驼峰及是否缩进进行json格式化。
如何对datetime类型对象进行格式化输出。
web层通过拓展abpjsonresult,指定时间格式。
前端,通过将json日期转换为js的date类型,再格式化输出。
webapi,通过在moduel中指定dateformatstring。
以上所述是小编给大家介绍的abp入门系列之json格式化,希望对大家有所帮助