欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ABP入门系列之Json格式化

程序员文章站 2023-11-27 17:53:40
讲完了分页功能,这一节我们先不急着实现新的功能。来简要介绍下abp中json的用法。为什么要在这一节讲呢?当然是做铺垫啊,后面的系列文章会经常和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格式化,希望对大家有所帮助