当前位置: 移动技术网 > IT编程>开发语言>.net > Asp.Net Core 轻松学-实现跨平台的自定义Json数据包

Asp.Net Core 轻松学-实现跨平台的自定义Json数据包

2018年12月03日  | 移动技术网IT编程  | 我要评论

31省养老金方案,牛娃闯都市,中国十大高薪职业

前言

    在前后端分离的业务开发中,我们总是需要返回各种各样的数据包格式,一个良好的 json 格式数据包是我们一贯奉行的原则,下面就利用 json.net 来做一个简单具有跨平台的序列化数据包实现类。

1. 应用 json.net

  • 1.1 首先在项目中引用 nuget 包

  • 1.2 编写一个 jsonreturn 结果包装类,继承自 contentresult ,并重写 contentresult 方法 executeresult(actioncontext context)
   public partial class jsonreturn : contentresult
    {
        public int code { get; protected set; }
        public string message { get; protected set; }
        public hashtable data { get; protected set; } = new hashtable();
        public bool success { get { return this.code == 0; } }

        public jsonreturn(int code, string message) { this.code = code; this.setmessage(message); }

        public jsonreturn setmessage(string value) { this.message = value; return this; }

        public jsonreturn setdata(params object[] value)
        {
            this.data.clear();
            return this.appenddata(value);
        }

        public jsonreturn appenddata(params object[] value)
        {
            if (value?.length < 2)
                return this;

            for (int a = 0; a < value.length; a += 2)
            {
                if (value[a] == null) continue;
                this.data[value[a]] = a + 1 < value.length ? value[a + 1] : null;
            }
            return this;
        }

        private void tojson(actioncontext context)
        {
            this.contenttype = "text/json;charset=utf-8;";
            this.content = jsonconvert.serializeobject(this);
        }

        public override task executeresultasync(actioncontext context)
        {
            tojson(context);
            return base.executeresultasync(context);
        }

        public override void executeresult(actioncontext context)
        {
            tojson(context);
            base.executeresult(context);
        }

        /// <summary>
        /// 成功 0
        /// </summary>
        public static jsonreturn 成功 { get { return new jsonreturn(0, "成功"); } }

        /// <summary>
        ///  失败 500
        /// </summary>
        public static jsonreturn 失败 { get { return new jsonreturn(500, "失败"); } }
    }
  • 在 jsonreturn 类中,定义了一个存储业务数据对象的 hashtable 对象,在接口中可以往该对象中写入需要序列化的数据,并重写了 contentresult 的 executeresultasync 和 executeresult 方法,在方法内实现 jsonresult 对象的序列化,最后提供了两个静态属性方便调用;在 jsonreutrn 类中,最重要的是定义了成功和失败的 code ,默认 0 =成功,500=失败,这样就约定了所有客户端都强制使用该协议,完成了标准的统一。

  • 1.3 在控制器中将此对象返回

        [httpget]
        public actionresult get()
        {
            userinfo info = new userinfo()
            {
                age = 22,
                gender = true,
                name = "ron.lang",
                regtime = datetime.now
            };
            return jsonreturn.成功.setdata("detail", info);
        }
  • 1.4 运行程序,得到如下内容
{
  "code": 0,
  "message": "成功",
  "data": {
    "detail": {
      "name": "ron.lang",
      "gender": true,
      "age": 22,
      "regtime": "2018-12-02t16:27:17.3289028+08:00"
    }
  }
}

2. 改造

  • 2.1 上面的结果还可以接受,只是有一点小瑕疵,比如 bool 类型和字段名称大小写的问题,以及时间格式,都不是太友好,对于跨平台来说,会存在一些问题,下面我们改造一下,使得输出的字段名称全部消息,bool 类型转换为数字 0/1,时间转换为 unix 格式;首先创建 3 个自定义 json 序列化类

  • 2.2 lowercasecontractresolver.cs 转换字段名称为小写,该类非常简单,仅有一行核心代码

public class lowercasecontractresolver : defaultcontractresolver
{
    protected override string resolvepropertyname(string propertyname)
    {
        return propertyname.tolower();
    }
}
  • 2.3 booleanconverter.cs 将 bool 类型转换为数字 0/1
public class booleanconverter : jsonconverter
{
    public override bool canconvert(type objecttype)
    {
        return objecttype == typeof(bool) || objecttype == typeof(nullable<bool>);
    }

    public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)
    {
        if (reader.value == null)
            return null;

        return convert.toboolean(reader.value);
    }

    public override void writejson(jsonwriter writer, object value, jsonserializer serializer)
    {
        if (value == null)
            writer.writenull();
        else
        {
            uint32 val = convert.touint32(convert.toboolean(value));
            writer.writevalue(val);
        }
    }
}
  • 2.4 datetimeconverter.cs unix 时间格式转换类
public class datetimeconverter : datetimeconverterbase
{
    public static datetime greenwich_mean_time = timezoneinfo.converttime(new datetime(1970, 1, 1), timezoneinfo.local);
    public override bool canconvert(type objecttype)
    {
        return objecttype == typeof(datetime) || objecttype == typeof(nullable<datetime>);
    }

    public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)
    {
        if (reader.value == null)
            return null;

        if (canconvert(objecttype))
        {
            if (string.isnullorempty(reader.value.tonullorstring()))
                return reader.value;

            if (reader.value is string)
            {
                if (datetime.tryparse(reader.value.tostring(), out datetime dt))
                    return dt;
                else
                    return reader.value;
            }
            else
                return new datetime(greenwich_mean_time.ticks + convert.toint64(reader.value) * 10000).tolocaltime();
        }
        else
            return reader.value;
    }

    public override void writejson(jsonwriter writer, object value, jsonserializer serializer)
    {
        if (value == null)
            writer.writenull();
        else
        {
            long val = 0;
            if (value.gettype() == typeof(datetime))
            {
                datetime dt = convert.todatetime(value);
                val = (dt.touniversaltime().ticks - greenwich_mean_time.ticks) / 10000;
            }
            else
                val = convert.toint64(value);

            writer.writevalue(val);
        }
    }
}
  • 2.5 最后一步,全局注册 jsonsettings 到系统中,打开 startup.cs 文件,在 startup 方法中写入以下内容
        public startup(iconfiguration configuration, ihostingenvironment env)
        {
            jsonconvert.defaultsettings = () =>
            {
                var st = new jsonserializersettings
                {
                    formatting = formatting.indented
                };

                st.converters.add(new booleanconverter());
                st.converters.add(new datetimeconverter());
                st.contractresolver = new lowercasecontractresolver();

                return st;
            };
        }
  • 2.6 运行程序,接口输出以下内容,完成
{
  "code": 0,
  "message": "成功",
  "data": {
    "detail": {
      "name": "ron.lang",
      "gender": 1,
      "age": 22,
      "regtime": 1543739815980
    }
  }
}

结语

通过继承 contentresult 实现自定义的序列化数据包,这是刚需;为了实现跨平台的要求,我们还自定义 jsonsettings 实现各种类型的自定义转换,在实际项目开发中,这是非常有用的。

代码下载

https://files.cnblogs.com/files/viter/ron.jsontest.zip

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网