ABP入门系列之Json格式化

2019-05-25 22:38:30丽君

在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,那我们就只能自己动手了,具体代码请参考4种解决json日期格式问题的办法的第四种办法。

当有异常发生时,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;
  }
 }
}