• 我记录网站综合系统 技术原理解析[5:JSON 序列化 反序列化]


    源代码位置:wojilu\Serialization

    wojilu作为一个成熟的框架,不但有整个完整的MVC框架,还具有很多可以独立供大家使用的功能模块。

    可能您已经有自己的框架了,不过,您还是可以使用尝试一下他所提供的小类库,帮助你提高开发效率。

    这节就来介绍一下JSON的序列化和反序列化。

    整个JSON的类库的方法入口时JSON.cs文件中的JSON类。我们看看他所具有的各种方法吧:

    这里主要是各种发序列化的功能

    /// 将字典序列化为 json 字符串
    public static String DicToString( Dictionary<String, object> dic ) 
    /// 将 json 字符串反序列化为对象
    public static Object ToObject( String oneJsonString, Type t )
    /// 将 json 字符串反序列化为对象
    public static T ToObject<T>( String jsonString )
    /// 将 json 字符串反序列化为对象列表
    public static List<T> ToList<T>( String jsonString )
    /// 将 json 字符串反序列化为字典对象的列表
    public static List<Dictionary<String, object>> ToDictionaryList( String jsonString ) 
    /// 将 json 字符串反序列化为字典对象
    public static Dictionary<String, object> ToDictionary( String oneJsonString )

    在另一个类JsonString.cs中,我们可以看到很多序列化的功能

     1         /// <param name="isBreakline">是否换行(默认不换行,阅读起来更加清晰)</param>
     2         /// <param name="withQuotation">属性名是否使用引号(默认不启用)</param>
     3 
     4 /// 将对象转换成 json 字符串
     5 public static String Convert( Object obj )
     6 public static String Convert( Object obj, Boolean isBreakline ) 
     7 /// 将对象数组转换成 json 字符串
     8 public static String ConvertArray( object[] arrObj )
     9 /// 将对象列表转换成 json 字符串
    10 public static String ConvertList( IList list ) 
    11 public static String ConvertList( IList list, Boolean isBreakline ) 
    12 /// 将字典 Dictionary 转换成 json 字符串
    13 public static String ConvertDictionary( IDictionary dic )
    14 public static String ConvertDictionary( IDictionary dic, Boolean isBreakline )
    15 /// 将对象转换成 json 字符串
    16 public static String ConvertObject( Object obj )
    17 public static String ConvertObject( Object obj, Boolean isBreakline )
    18 public static String ConvertObject( Object obj, Boolean isBreakline, Boolean withQuotation )

    拥有这么多函数,可以将很多复杂对象转换为JSON,也可以还原JSON为复杂对象了。

    当然这是一篇技术文章,我们还是要从技术角度来分析一下wojilu的JSON的技术面的东西。

    说到复杂对象的序列化,以前的XML,Android的Parcel对象[前段时间在研究Android(本人研究范围从Winform到ASP到Mainfraim到DB),里面也有一个序列化的Parcel对象,Java写的],现在的JSON,思想都是一样的。

    1。通过反射Reflection来获得类里面的所有属性,如果属性是基本对象[那些值引用,放在栈上的家伙们],直接调用相应序列化方法,序列化成JSON,遇上非基本类型,继续递归,遍历非基本对象的所有属性,能序列化的序列化,不行继续递归。

    反射的语句:

    PropertyInfo[] properties = obj.GetType().GetProperties( BindingFlags.Public | BindingFlags.Instance );

    遍历所有属性,能序列化就序列化

                foreach (PropertyInfo info in propertyList) {
                    
    if (info.IsDefined( typeof( NotSerializeAttribute ), false )) {
                        
    continue;
                    }
                    Object propertyValue 
    = ReflectionUtil.GetPropertyValue( obj, info.Name );

                    String jsonValue;
                    
    if (info.PropertyType.IsArray) {
                        jsonValue 
    = ConvertArray( (object[])propertyValue );
                    }
                    
    else if (rft.IsInterface( info.PropertyType, typeof( IList ) )) {
                        jsonValue 
    = ConvertList ( (IList)propertyValue, isBreakline );
                    }
                    
    else {
                        jsonValue 
    = Convert( propertyValue, isBreakline );
                    }

                    
    if (withQuotation) {
                        builder.AppendFormat( 
    "\"{0}\":{1}", info.Name, jsonValue );
                    }
                    
    else {
                        builder.AppendFormat( 
    "{0}:{1}", info.Name, jsonValue );
                    }

                    builder.Append( 
    "" );
                    
    if (isBreakline) builder.AppendLine();

                }
                String result 
    = builder.ToString().Trim().TrimEnd( ',' );
                
    if (isBreakline) result += Environment.NewLine;
                
    return result + " }";
            }

    2.各种基本类型的序列化

      

       字符串的序列化:转义符的处理。

       转义符,就是那些引号,斜杠 等家伙们。他们混在字符串里面,但是并非是字符串。

       在将对象转化为字符串的时候,如果遇上字符串转为JSON字符串的时候,请注意这些小地方的处理。  

                if (t == typeof( String )) {
                    
    return "\"" + obj.ToString().Replace( @"\"@"\\" ).Replace( "\"""\\" + "\"" ).Replace( "\r""" ).Replace( "\n""" ) + "\""// 转义双引号,消除换行
                }

     日期的序列化 在日期前后加上 斜杠

    if (t == typeof( DateTime )) return "\"" + obj.ToString() + "\"";

    逻辑值的序列化:转换为小写

    if (t == typeof( Boolean )) return obj.ToString().ToLower();

    数字:直接转换

    おまけ:

    一时忍不住,贡献一下我以前VBNET的XML序列化的代码,作为礼物给大家。。。。我写了10年VB了。。。

      1 Imports System
      2 Imports System.Xml
      3 Imports System.Xml.Serialization
      4 Imports System.IO
      5 Imports Microsoft.VisualBasic
      6 ''' <summary>
      7 ''' 将对象或哈希表从文件读取或写入的方法集合
      8 ''' </summary>
      9 ''' <remarks></remarks>
     10 Public Module IOSystemBase
     11     ''' <summary>
     12     ''' 从二进制文件中读取哈希表
     13     ''' </summary>
     14     ''' <param name="StrFileName">文件名</param>
     15     ''' <returns>哈希表</returns>
     16     ''' <remarks></remarks>
     17     Function ReadHashTableFromBinaryFile(ByVal StrFileName As StringAs Hashtable
     18         Dim ReturnHashTable As Hashtable
     19 
     20         Dim formatter = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
     21         Dim stream = New IO.FileStream(StrFileName, IO.FileMode.Open)
     22         Try
     23             ReturnHashTable = CType(formatter.Deserialize(stream), Hashtable)
     24         Catch
     25             ReturnHashTable = Nothing
     26         Finally
     27             stream.Close()
     28         End Try
     29         Return ReturnHashTable
     30     End Function
     31     ''' <summary>
     32     ''' 将哈希表写入二进制文件
     33     ''' </summary>
     34     ''' <param name="strFileName">文件名</param>
     35     ''' <param name="obj">哈希表</param>
     36     ''' <remarks></remarks>
     37     Sub WriteHashTableToBinaryFile(ByVal strFileName As StringByVal obj As Hashtable)
     38         Dim formatter = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
     39         Dim stream = New IO.FileStream(strFileName, IO.FileMode.OpenOrCreate)
     40         formatter.Serialize(stream, obj)
     41         stream.Close()
     42     End Sub
     43     ''' <summary>
     44     ''' 从XML文件中读取哈希表
     45     ''' </summary>
     46     ''' <param name="StrFileName">文件名</param>
     47     ''' <returns>哈希表</returns>
     48     ''' <remarks></remarks>
     49     Function ReadHashTableXMLFile(ByVal StrFileName As StringAs Hashtable
     50         Dim ReturnHashTable As Hashtable
     51         Dim formatter = New System.Xml.Serialization.XmlSerializer(GetType(Hashtable))
     52         Dim stream = New IO.FileStream(StrFileName, IO.FileMode.Open)
     53         Try
     54             ReturnHashTable = CType(formatter.Deserialize(stream), Hashtable)
     55         Catch
     56             ReturnHashTable = Nothing
     57         Finally
     58             stream.Close()
     59         End Try
     60         Return ReturnHashTable
     61     End Function
     62     ''' <summary>
     63     ''' 将哈希表写入XML文件
     64     ''' </summary>
     65     ''' <param name="strFileName">文件名</param>
     66     ''' <param name="obj">哈希表</param>
     67     ''' <remarks></remarks>
     68     Sub WriteHashTableToXMLFile(ByVal strFileName As StringByVal obj As Hashtable)
     69         Dim formatter = New System.Xml.Serialization.XmlSerializer(GetType(Hashtable))
     70         Dim stream = New IO.FileStream(strFileName, IO.FileMode.OpenOrCreate)
     71         formatter.Serialize(stream, obj)
     72         stream.Close()
     73     End Sub
     74     ''' <summary>
     75     ''' 将可XML序列化对象写入XML文件
     76     ''' </summary>
     77     ''' <param name="obj">对象</param>
     78     ''' <param name="mType">类型</param>
     79     ''' <param name="FileName">文件名</param>
     80     ''' <remarks>如果对象是不可序列化的类型,将返回错误</remarks>
     81     Sub WriteObjectToXMLFile(ByVal obj As ObjectByVal mType As Type, ByVal FileName As String)
     82         ' Use the constructor that takes a type and XmlRootAttribute.
     83         Dim serializer As New XmlSerializer(mType)
     84         Dim writer As New StreamWriter(FileName)
     85         serializer.Serialize(writer, obj)
     86         writer.Close()
     87     End Sub
     88     ''' <summary>
     89     ''' 从XML文件读取对象
     90     ''' </summary>
     91     ''' <param name="mType">类型</param>
     92     ''' <param name="FileName">文件名</param>
     93     ''' <returns>对象</returns>
     94     ''' <remarks>如果对象是不可序列化的类型,将返回错误</remarks>
     95     Function ReadObjectFromXMLFile(ByVal mType As Type, ByVal FileName As StringAs Object
     96         Dim serializer As New XmlSerializer(mType)
     97         Dim Reader As New StreamReader(FileName)
     98         Dim Rtn As Object
     99         Rtn = serializer.Deserialize(Reader)
    100         Reader.Close()
    101         Return Rtn
    102     End Function
    103     ''' <summary>
    104     ''' 如果没有指定目录,则创建
    105     ''' </summary>
    106     ''' <param name="strDirectoryPath">指定目录</param>
    107     ''' <remarks></remarks>
    108     Sub CreateDirectoryWhenNotExists(ByVal strDirectoryPath As String)
    109         If IO.Directory.Exists(strDirectoryPath) = False Then
    110             IO.Directory.CreateDirectory(strDirectoryPath)
    111         End If
    112     End Sub
    113 End Module

    我记录网址 http://www.wojilu.com/

    欢迎大家加入我记录开发团队

  • 相关阅读:
    Quartz.net -- Corn表达式
    ASP.NET Core 3.x RESTful API学习记录--获取父子关系资源
    ASP.NET Core 3.x RESTful API学习记录--AutoMapper简单使用
    ASP.NET Core 3.x RESTful API学习记录--ActionResult<T>
    ASP.NET Core 3.x RESTful API学习记录-- 面向外部的Model
    ASP.NET Core 3.x RESTful API学习记录--内容协商
    ASP.NET Core 3.x RESTful API学习记录--HTTP 状态码;错误和故障
    ASP.NET Core 3.x RESTful API学习记录--HTTP 方法
    ASP.NET Core 3.x RESTful API学习记录--API的对外合约
    asp.net core2 mvc 基础教程--CI/CD Azure DevOps
  • 原文地址:https://www.cnblogs.com/TextEditor/p/2080018.html
Copyright © 2020-2023  润新知