序列化对大家来说应该都不陌生,特别是现在大量使用WEBAPI,JSON满天飞,序列化操作应该经常出现在我们的代码上。

而我们最常用的序列化工具应该就是Newtonsoft.Json,当然你用其它工具类也是没问题的,我们重点讲的不是这个工具,我们的重点是高效的可自定义控制的序列化操作。

首先我们说一下大致的序列化原理:

一般情况下,我们把一个实体类,或是数据列表传给工具类(这里我拿Newtonsoft.Json做例子,其它的也是类似的)如:

class ClassTest{

public string aa{get;set;}

public string bb{get;set;}
}

var jsonStr=Newtonsoft.Json.JsonConvert.SerializeObject(new ClassTest());

得到的jsonStr="{\"aa\":null,\"bb\":null}";

这个时候我们就在想,序列化是怎么完成的呢,为什么我只要给他一个类,他就能帮我转化成一个JSON字符串呢?(应该有点开发年头的老鸟心里都有数,我还是多啰嗦几句,给新人看一下)

其实默认情况下它是使用了反射,当我们得到一个类,想知道它有什么成员,以及成员分别是什么值的时候,我们就只能用反射来得到,通过元数据我们能得到任何我们想要的信息(不了解反射的朋友可以去查一下相关资料),反射用起来确实很方便,但是有个很大的问题,就是性能,反射是相当耗性能的,下面我会讲到怎么样不用反射来实现序列化。

因为我们今天讲的重点是自定义,所以我们先来谈谈如何自定义。

默认情况下序列化工具会反射我们所有的属性,然后将它们转化到字符串中,如果我们只想让部分属性序列化出来要怎么做呢?

可能有人会说,那我再建立一个类,里面只写部分属性不就好了,虽然这也是一个办法,不过我相信大家都知道这个方法有多LOW,因为我们的需求是不断变化的,可能我们一个类要应付几十种场景,不可能我们每个场景都要新建一类吧,而且后期需求还会变动,还会增加,所以这个方案不行(如果你只想应付一下老板这个方法还是行的...)

可能又有人说,这些序列化工具类都提供了对应的特性,只要我写在我的属性身上我就可以控制哪些显示,哪些不显示,哪些有什么默认值了比如:

[JsonProperty]
[JsonIgnore]
[DefaultValue(30)]
但是我想说的是你还是不能解决我们刚刚说的问题,因为一个类特性你只能写一次,你这样做虽然比刚刚好了一点,但是应付多个场景依然不行。
我们想要的解决方案是可以由我们程序自由控制哪些类本次需要在序列化字符串中,哪些不需要,我们只需要一个类就可以解决所有场景的问题,自由控制。
于是乎我们找到了一个方案 使用 ISerializable ,用它我们可以完全自定义序列化过程中的具体行为,不再需要反射来帮我们,我们自己来实现序列化的细节,这是最高效,最自由的一种方式,但是它也有一个缺点
就是过于繁琐。还是拿上面的类来做个例子:

class ClassTest: ISerializable{

#region  json序列化 反序列化

/// <summary>序列化时调用</summary>

public virtual void GetObjectData(SerializationInfo s, StreamingContext c)
{

if(!string.IsNullOrEmpty(aa))  //这里可以使用任何条件来控制是否序列化

{s.AddValue("aa", aa);}

s.AddValue("bb", bb);

}

/// <summary>反序列化时操作</summary>
protected ClassTest(SerializationInfo s, StreamingContext c)
{
SerializationInfoEnumerator sItem = s.GetEnumerator();
while (sItem.MoveNext())
{
switch (sItem.Name)
{
case "aa": aa = s.GetString("aa"); break;
case "bb": bb = s.GetString("bb"); break;

default: break;
}
}
}

#endregion

public string aa{get;set;}

public string bb{get;set;}
}

只需要继承这个接口,实现两个方法,就可以完全的自定义序列化过程了
可能又有人说你这里只说了JSON,还有XML序列化怎么办呢?不要急,XML也可以自定义,只要实现 IXmlSerializable,同样实现它里面定义的方法就可以了,我这里就不详细说了。
我们这样做了以后序列化的时候它就不会使用反射了,而是直接调用相应的接口方法,这样性能显著提高,同时你又可以根据自己的情况自定义序列的规则。
那我们刚刚说了它有一个缺点就是写起来太繁琐了,那我们怎么办呢,其实我是一直都有代码生成器,我写好了模版只要设计好数据库模型,我的实体类就自动生成出来了,根本不需要打任何代码,所以对我来说也不繁琐.
还有一个问题大家应该注意到了就是我所有的序列化判断是在类的方法里面写的,如果我想在外部调用的时候来控制哪些字段序列化,哪些不序列化怎么办呢,你这个也解决不了啊?
对,上面的例子确实解决不了,但是我还是有解决方案,我利用泛型把实体类做了改造,这样我就可以完全在外部来控制序列化了,这个具体的实现我会在后期的文章中在介绍我自己设计的开发框架时再详细说(如果大家有兴趣看的话)
说了半天好像完全没提到.NET core,现在要说它了,上面好个方案是可以用到之前的.net framework的各版本的,以及mono上也是可以运行的,但是现在最新的.NET core 就有点问题了,我最近想把我的开发框架
移植到.NET core上就出现了问题,它不支持ISerializable,本来我还以为是我用错了,后来查看了源码才发现是真的还不支持

因为.NET core才正式发布没多久,很多东西还不不是很完善,我在查这个问题的时候也是找了半天原因,所以我在这里也是给大家提个醒,这个东西暂时还没弄好,不过后面应该会弄好的,时间问题。

那么现阶段我们要怎么处理呢,其实很简单,既然序列化是把我们的类属生拼接成一个字符串,为什么我们不自己实现这个方法呢,只要用代码生成器帮我们生成这段代码,对我们来说也是很方便,高效的,应该说比以上方法都要高效。比如:


class ClassTest{


public string aa{get;set;}


public string bb{get;set;}

public string ToJson()

{

System.Text.StringBuilder sb = new System.Text.StringBuilder("{");

if(!string.IsNullOrEmpty(aa))  //这里可以使用任何条件来控制是否序列化

{sb.AppendFormat(",\"aa\":{0}", aa);}

sb.AppendFormat(",\"bb\":{0}", bb);

sb.Append("}");
return sb.ToString();

}

}

就这样写个方法就可以了,需要用到序列化的地方只需要用 new ClassTest().ToJson()就可以了,这样也很方便吧,同样的你想要外部调用时使用哪些序列化,后期我会再详细讲
其实小弟第一次发博客写文章,写的东西也很简单,没什么太大的技术含量,希望各位大神,大虾指点我的时候轻点拍砖,我也只是把我知道的一直在用的,感觉比较好用的分享出来而以,并不是来秀技术的,我也没什么技术好秀。
以上内容,完全手打原创,转载请注明出处!望各位大神指错!

.Net Core 自定义序列化格式的更多相关文章

  1. Newtonsoft.Json 自定义序列化格式转化器

    public static class JsonHelper { static JsonHelper() { Newtonsoft.Json.JsonSerializerSettings settin ...

  2. Newtonsoft.Json高级用法 1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  3. 使用Typescript重构axios(二十八)——自定义序列化请求参数

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  4. fastjson自定义序列化竟然有这么多姿势?

    本文介绍下fastjson自定义序列化的各种操作. 一.什么是fastjson? fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSO ...

  5. Gorm 预加载及输出处理(三)- 自定义时间格式

    前言 Gorm 中 time.Time 类型的字段在 JSON 序列化后呈现的格式为 "2020-03-11T18:26:13+08:00",在 Go 标准库文档 - time 的 ...

  6. Hive中自定义序列化器(带编码)

    hive SerDe的简介 https://www.jianshu.com/p/afee9acba686 问题 数据文件为文本文件,每一行为固定格式,每一列的长度都是定长或是有限制范围,考虑采用hiv ...

  7. POI对Excel自定义日期格式的读取

    用POI读取Excel数据:(版本号:POI3.7) 1.读取Excel private List<String[]> rosolveFile(InputStream is, String ...

  8. java中使用poi导入导出excel文件_并自定义日期格式

    Apache POI项目的使命是创造和保持java API操纵各种文件格式基于Office Open XML标准(OOXML)和微软的OLE复合文档格式(OLE2)2.总之,你可以读写Excel文件使 ...

  9. PHP序列化以及反序列化系列[1]--PHP序列化格式的写法

    反序列化:对单一的已序列化的变量进行操作,将其转换回 PHP 的值(zval). PHP序列化方式 PHP在序列化的时候会将相应的变量以对应的键值进行储存. 将一个类序列化的话,处理代码主要的 文件: ...

随机推荐

  1. Tomcat:bio nio 的设计

    BIO  由Acceptor接收Socket,将其转交给Worker来处理. NIO 由Acceptor接收Socket,将其转交给Poller来轮询处理.Poller再将可处理的Socket交给Wo ...

  2. 使用国内 maven 镜像 代替国外 mirror

    使用maven的都知道国外的maven下载一个是比较慢,一个是因为被墙,一些jar包无法下载,非常老火. 比如出现类似下面的错误: Unknown host repo.maven.apache.org ...

  3. 大数据挖掘: FPGrowth初识--进行商品关联规则挖掘

    @(hadoop)[Spark, MLlib, 数据挖掘, 关联规则, 算法] [TOC] 〇.简介 经典的关联规则挖掘算法包括Apriori算法和FP-growth算法.Apriori算法多次扫描交 ...

  4. 【转】分布式数据层 TDDL 来自:阿里巴巴

    淘宝根据自己的业务特点开发了TDDL(Taobao Distributed Data Layer 外号:头都大了 ©_Ob)框架,主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个 ...

  5. Linux文件和目录

    access() //检查是否调用进程有Access这个文件的权限,如果文件是一个符号链接,会将它解引用,成功返回0,失败返回-1设errno #include <unistd.h> in ...

  6. Linux rm 删除文件

    rm 删除文件rm -f 强制删除-i 提示-r 删除目录的时候-v 可实话 rm -rfv 多目录 不提示 [root@wang whp]# touch .txt [root@wang whp]# ...

  7. STM32的USART

    转载自:http://www.cnblogs.com/TrueElement/archive/2012/09/14/2684298.html 几个问题: 1.状态寄存器(USART_SR)中的TC(T ...

  8. 理解 QEMU/KVM 和 Ceph(1):QEMU-KVM 和 Ceph RBD 的 缓存机制总结

    本系列文章会总结 QEMU/KVM 和 Ceph 之间的整合: (1)QEMU-KVM 和 Ceph RBD 的 缓存机制总结 (2)QEMU 的 RBD 块驱动(block driver) (3)存 ...

  9. 基于内容产品的MVP探索

    王凯:凯叔讲故事的创始人 1.精益创业有以下3个过程: ——假设:价值假设和增长假设 ——认知:验证认知 ——行动:MVP(最小化可行产品) 2.互联网时代内容该如何定价: ——对于一家初创公司,最重 ...

  10. [No000044]你是否还傻到把最好的留在最后?

    想写这篇文章很久了. 因为一直觉得我们人有一个毛病,总是喜欢将最好的东西留到最后才享用,或者等最后再给别人. 但人们往往忽略了至关重要的一点,就是这个最好有一个保质期.可以说人能拥有的快乐触发点.有机 ...