序列化对大家来说应该都不陌生,特别是现在大量使用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. .NET领域驱动设计—看DDD是如何运用设计模式颠覆传统架构

    阅读目录: 1.开篇介绍 2.简单了解缘由(本文的前期事宜) 3.DomainModel扩展性(运用设计模式设计模型变化点) 3.1.模型扩展性 3.2.设计模式的使用(苦心专研的设计模式.设计思想可 ...

  2. python爬取并下载麦子学院所有视频教程

    一.主要思路 scrapy爬取是有课程地址及名称 使用multiprocessing进行下载 就是为了爬点视频,所以是简单的代码堆砌 想而未实行,进行共享的方式 二.文件说明 itemsscray字段 ...

  3. 烂泥:mysql帮助命令使用说明

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 在安装.管理和使用mysql过程中,你是不是需要记忆很多的mysql命令.而且对于新手来说,很不多的命令不知道该如何应用,对于老手来说很多命令时间长了忘 ...

  4. iOS 判断内容是否是中文,两种实现

    用category实现 新建类别文件,代码 .h文件 #import <Foundation/Foundation.h> @interface NSString (Valid) - (BO ...

  5. WIN32 API编程之 透明static

    createwindow可以直接创建一个staitc,但这个static是不透明的,如果我们把窗口背景设置为GRAY_BRUSH,则static会很明显的有一个白色背景,一般来说这样肯定很难看. 可以 ...

  6. 非常不错的点餐系统应用ios源码完整版

    该源码是一款非常不错的点餐系统应用,应用源码齐全,运行起来非常不错,基本实现了点餐的一些常用的功能,而且界面设计地也很不错,是一个不错的ios应用学习的例子,喜欢的朋友可以下载学习看看,更多ios源码 ...

  7. html5语法

    html5语法沿用html语法,但更简单,更人性化. 一.DOCTYPE及字符编码 DOCTYPE:<!doctype html>或者<!DOCTYPE html>因为html ...

  8. 校园导游系统(C++实现,VC6.0编译,使用EasyX图形库)

    运行效果: 说明: 由于当年还不会使用多线程,所以很多获取用户点击的地方都是使用循环实现的...CPU占用率会比较高. 代码: //校园导游系统.cpp 1 #include <graphics ...

  9. QC学习一:Windows环境中Quality Center 9.0安装详解

    一.安装前准备 1.安装环境:windows XP.SQL Server2005 2.准备安装文件:Quality Center 9.0 (qc10以上,包括qc10,qc只支持安装在服务器操作系统上 ...

  10. java 27 - 9 反射之 动态代理的概述和实现

    代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象. 举例:春季回家买票让人代买 动态代理: 在程序运行过程中产生的这个对象 而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以 ...