博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#对象JSON序列化与客户端JavaScript反序列化
阅读量:6296 次
发布时间:2019-06-22

本文共 19706 字,大约阅读时间需要 65 分钟。

  首先声明, 由于个人在写这个C#对象JSON序列化之前没有查看过相关JSON序列化的文章和书籍, 所以实现步骤和达到的效果可能与大家所知道的不一样,我的观点是,方便使用即可。 由于技术有限,这个类库会有一些遗漏的元素和不足之处, 如果有其他见解,还请不吝赐教。

  在编写web应用程序的时候,我们经常会用到ajax技术,而在客户端与服务器进行ajax异步通信的时候,我们往往需要从客户端提交一些数据到服务器,或是从服务器响应一些数据给客户端,但由于客户端与服务器端的数据格式不统一, 所以我们无法直接将服务器端的C#对象直接发送给客户端,这时候我们就需要用到JSON对象。

  ASP.NET的MVC框架中直接提供了JSON对象序列化的方法,但是ASP.NET中貌似没有直接提供,可以通过引用第三方插件或者是MVC中的类库来使用JSON序列化,不过由于个人比较懒,不想引用,加上想巩固一下之前学的一些知识,所以就决定自己写一个够用的C#的JSON序列化和客户端JavaScript的反序列化了(实际上客户端的JavaScript反序列化不是我写的。。我只是改了一点点)。

  上面都是扯淡,下面开始介绍这个自定义JSON序列化类型的功能:

C#服务器端:

  功能:将C#对象序列化为一个JSON字符串

  命名空间HourglassHelper

  类名HourglassJson(静态类

  主要方法string Parse(静态方法),该方法有四个重载:

        ·Parse(params object[] datas)

        ·Parse(HgJSonItemArrayOption arrayOption, params object[] datas)

        ·Parse(bool convertOblique, params object[] datas)

        ·Parse(HgJSonItemArrayOption arrayOption, bool convertOblique, params object[] datas)

  参数说明datas:对象数组,调用时可传入任意多个对象

        convertOblique:是否将字符串类型对象的值中的"/"进行转义,以防止其进行转义,默认值true(也就是默认会将"/"转换为"//")

        arrayOption:数组对象设置,默认值HgJSonItemArrayOption.None

        ·HgJSonItemArrayOption.AllObject            //将所有对象都封装为JavaScript数组

        ·HgJSonItemArrayOption.OnlyComplex          //仅仅封装复杂对象为JavaScript数组(不论长度)

        ·HgJSonItemArrayOption.OnlyOriginal            //仅仅封装初始传入对象为JavaScript数组(不论长度,但是长度大于1的C#数组对象还是会被封装为JavaScript数组)

        ·HgJSonItemArrayOption.OnlyComplexWithoutOriginal  //仅仅封装复杂对象为JavaScript数组,如果初始传入对象的长度为1,那么就不封装初始传入对象

        ·HgJSonItemArrayOption.None              //长度大于1的复杂对象封装为JavaScript数组

 

JavaScript客户端:

  额、好吧,其实客户端解析我服务器端序列化后JSON对象代码是从《JavaScript语言精粹》最后面的一个Json_Parse上直接copy过来的,然后在时候的时候有一点点小问题。那就是服务器端在序列化C#对象的时候,会把Boolean对象的true和false序列化为"True"和"False",这样是开头大写的,但是《JavaScript语言精粹》提供的反序列化代码中,在解析true和false的时候,只将"true"和"false"映射为对应的boolean值,但是不会忽略大小写,这个问题其实是可以在写服务器端代码的时候解决的,不过我认为客户端在解析JSON字符串的时候,在对boolean值进行解析的时候,应该忽略大小写的,所以在解析boolean那块儿稍微改了一下。当然如果觉得这样不合适,可以自行再改回去。

 

服务器端代码:

 

/** * Version : 1.0.1 * Author  : Hourglass * Date    : 2014-1-22 */using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Text;using System.Web;namespace HourglassHelper{    public static class HourglassJson    {        private static bool _convertOblique = true;        private static HgJSonItemArrayOption _arrayOption = HgJSonItemArrayOption.None;        private static bool isCurrentList = false;        private static bool isPreviousList = false;        ///         /// 将多个任意类型的对象转换为JSon对象        ///         /// 需要被转换的JSon对象        /// 
JSon字符串值
public static string Parse(params object[] datas) { string hgJson; if (datas.Length > 1 || _arrayOption == HgJSonItemArrayOption.OnlyOriginal) { hgJson = ArrayToHgJson(datas); } else { if (datas.Length == 1 && typeof(IList).IsAssignableFrom(datas[0].GetType())) { hgJson = ArrayToHgJson(datas); hgJson = "[" + hgJson.Trim('[', ']') + "]"; } else { hgJson = ConvertAsHgJson(datas[0]); } if (_arrayOption == HgJSonItemArrayOption.OnlyComplexWithoutOriginal) { hgJson = hgJson.Remove(0, 1).Remove(hgJson.Length - 2, 1); } } return hgJson; } /// /// 将多个任意类型的对象转换为JSon对象 /// /// 是否不论传入数据个数是否大于1,始终将JSON保存为数组,默认false /// 需要被转换的JSon对象 ///
JSon字符串值
public static string Parse(HgJSonItemArrayOption arrayOption, params object[] datas) { _arrayOption = arrayOption; return Parse(datas); } /// /// 将多个任意类型的对象转换为JSon对象 /// /// 是否需要将字符串中的'/'替换为'//',默认true /// 需要被转换的JSon对象 ///
JSon字符串值
public static string Parse(bool convertOblique, params object[] datas) { if (datas.Length == 0) { return ConvertAsHgJson(convertOblique); } _convertOblique = convertOblique; return Parse(datas); } /// /// 将多个任意类型的对象转换为JSon对象 /// /// 是否不论传入数据个数是否大于1,始终将JSON保存为数组,默认false /// 是否需要将字符串中的'/'替换为'//',默认true /// 需要被转换的JSon对象 ///
JSon字符串值
public static string Parse(HgJSonItemArrayOption arrayOption, bool convertOblique, params object[] datas) { _arrayOption = arrayOption; _convertOblique = convertOblique; return Parse(datas); } /// /// 将一个对象转换为自定义JSon对象 /// /// 需要被转换的对象 ///
JSon字符串值
private static string ConvertAsHgJson(object item) { string jsonValue; if (item == null) { return "null"; } Type type = item.GetType(); string typeName = type.Name.ToLower(); switch (typeName) { case "string": case "char": case "datetime": if (_convertOblique) { jsonValue = "\"" + EasyTypeToHgJson(item).Replace("\\", "\\\\") + "\""; } else { jsonValue = "\"" + EasyTypeToHgJson(item) + "\""; } break; case "byte": case "int16": case "int32": case "int64": case "uint16": case "uint32": case "uint64": case "boolean": case "single": case "double": case "decimal": jsonValue = EasyTypeToHgJson(item); break; default: { if (typeof(IList).IsAssignableFrom(type)) {//实现IList(包括数组) isCurrentList = true; List objs = new List(); foreach (object it in (IEnumerable)item) { objs.Add(it); } jsonValue = HourglassJson.ArrayToHgJson(objs.ToArray()); isCurrentList = false; isPreviousList = true; } else if (typeof(IDictionary).IsAssignableFrom(type)) {//实现IDictionary Dictionary
dic = new Dictionary
(); foreach (var it in (IEnumerable)item) { Type itType = it.GetType(); string key = itType.InvokeMember("Key", BindingFlags.GetProperty, null, it, null).ToString(); object value = itType.InvokeMember("Value", BindingFlags.GetProperty, null, it, null); dic.Add(key, value); } jsonValue = DicToHgJson(dic); } else {//用户自定义类或结构体(class, struct) jsonValue = ClassStructToHgJson(item); } //待补充,非IsPrimitive的类型应该还有别的类型 if (!isCurrentList && !isPreviousList && _arrayOption != HgJSonItemArrayOption.None) { if (_arrayOption == HgJSonItemArrayOption.OnlyComplex || _arrayOption == HgJSonItemArrayOption.OnlyComplexWithoutOriginal) { jsonValue = "[" + jsonValue + "]"; } } } break; } if (!isPreviousList && _arrayOption == HgJSonItemArrayOption.AllObject) { jsonValue = "[" + jsonValue + "]"; } isPreviousList = false; return jsonValue; } ///
/// 将Class和Struct转换为自定义JSon对象 /// ///
Class或Struct对象 ///
JSon字符串值
private static string ClassStructToHgJson(object item) { StringBuilder classStructHgJson = new StringBuilder(); Type type = item.GetType(); PropertyInfo[] properties = type.GetProperties(); classStructHgJson.Append("{"); foreach (PropertyInfo p in properties) { object propertyValue = type.InvokeMember(p.Name, BindingFlags.GetProperty, null, item, null); classStructHgJson.Append(string.Format("\"{0}\":{1}", p.Name, HourglassJson.ConvertAsHgJson(propertyValue))); classStructHgJson.Append(","); } classStructHgJson.Remove(classStructHgJson.Length - 1, 1); classStructHgJson.Append("}"); return classStructHgJson.ToString(); } ///
/// 将数组转换为自定义JSon对象 /// ///
数组对象 ///
JSon字符串值
private static string ArrayToHgJson(object[] items) { StringBuilder hgJson = new StringBuilder(); hgJson.Append("["); foreach (object item in items) { string itemHgJson = ConvertAsHgJson(item); hgJson.Append(itemHgJson); hgJson.Append(","); } hgJson.Remove(hgJson.Length - 1, 1); hgJson.Append("]"); return hgJson.ToString(); } ///
/// 将IDictionary转换为自定义JSon对象 /// ///
IDictionary对象 ///
JSon字符串值
private static string DicToHgJson(IDictionary
dictionary) { StringBuilder dicHgJsonBuilder = new StringBuilder(); dicHgJsonBuilder.Append("{"); foreach (KeyValuePair
item in dictionary) { string itemValueHgJson = HourglassJson.ConvertAsHgJson(item.Value); string itemHgJson = string.Format("\"{0}\":{1}", item.Key, itemValueHgJson); dicHgJsonBuilder.Append(itemHgJson); dicHgJsonBuilder.Append(","); } dicHgJsonBuilder.Remove(dicHgJsonBuilder.Length - 1, 1); dicHgJsonBuilder.Append("}"); return dicHgJsonBuilder.ToString(); } ///
/// 简单类型转自定义JSon对象。 /// 简单类型包括string, char, byte, short, int, long, ushort, uint, ulong, float, double, decimal, bool, datetime /// ///
简单类型对象 ///
JSon字符串值
private static string EasyTypeToHgJson(object item) { return item.ToString(); } } public enum HgJSonItemArrayOption { AllObject, //将所有对象都封装为数组 OnlyComplex, //仅仅封装复杂对象为数组(不论长度) OnlyOriginal, //仅仅封装初始传入对象为数组(不论长度,但是长度大于1的数组对象还是会被封装为数组) OnlyComplexWithoutOriginal, //仅仅封装复杂对象,如果初始传入对象的长度为1,那么就不封装初始传入对象 None //长度大于1的复杂对象封装为数组 }}

 

  

 

 

客户端代码:

(function (window) {    var json_parse = (function () {        var at,     // The index of the current character            ch,     // The current character            escapee = {                '"': '"',                '\\': '\\',                '/': '/',                b: '\b',                f: '\f',                n: '\n',                r: '\r',                t: '\t'            },            text,            error = function (m) {// Call error when something is wrong.                throw {                    name: 'SyntaxError',                    message: m,                    at: at,                    text: text                };            },            next = function (c, cc) {// If a c parameter is provided, verify that it matches the current character.cc -> check case                if (cc) {                    if (c && c.toLowerCase() !== ch.toLowerCase()) {                        error("Expected '" + c + "' instead of '" + ch + "'");                    }                } else {                    if (c && c !== ch) {                        error("Expected '" + c + "' instead of '" + ch + "'");                    }                }                // Get the next character. When there are no more characters,                // return the empty string.                ch = text.charAt(at);                at += 1;                return ch;            },            number = function () {// Parse a number value.                var number,                    string = '';                if (ch === '-') {                    string = '-';                    next('-');                }                while (ch >= '0' && ch <= '9') {                    string += ch;                    next();                }                if (ch === '.') {                    string += '.';                    while (next() && ch >= '0' && ch <= '9') {                        string += ch;                    }                }                if (ch === 'e' || ch === 'E') {                    string += ch;                    next();                    if (ch === '-' || ch === '+') {                        string += ch;                        next();                    }                    while (ch >= '0' && ch <= '9') {                        string += ch;                        next();                    }                }                number = +string;                if (!isFinite(number)) {                    error("Bad number");                } else {                    return number;                }            },            string = function () {// Parse a string value.                var hex,                    i,                    string = '',                    uffff;                // When parsing for string values, we must look for " and \ characters.                if (ch === '"') {                    while (next()) {                        if (ch === '"') {                            next();                            return string;                        } else if (ch === '\\') {                            next();                            if (ch === 'u') {                                uffff = 0;                                for (i = 0; i < 4; i += 1) {                                    hex = parseInt(next(), 16);                                    if (!isFinite(hex)) {                                        break;                                    }                                    uffff = uffff * 16 + hex;                                }                                string += String.fromCharCode(uffff);                            } else if (typeof escapee[ch] === 'string') {                                string += escapee[ch];                            } else {                                break;                            }                        } else {                            string += ch;                        }                    }                }                error("Bad string");            },            white = function () {// Skip whitespace.                while (ch && ch <= ' ') {                    next();                }            },            word = function () {// true, false, or null.                switch (ch.toLowerCase()) {                    case 't':                        next('t', true);                        next('r', true);                        next('u', true);                        next('e', true);                        return true;                    case 'f':                        next('f', true);                        next('a', true);                        next('l', true);                        next('s', true);                        next('e', true);                        return false;                    case 'n':                        next('n', true);                        next('u', true);                        next('l', true);                        next('l', true);                        return null;                }                error("Unexpected '" + ch + "'");            },            value,  // Place holder for the value function.            array = function () {// Parse an array value.                var array = [];                if (ch === '[') {                    next('[');                    white();                    if (ch === ']') {                        next(']');                        return array;   // empty array                    }                    while (ch) {                        array.push(value());                        white();                        if (ch === ']') {                            next(']');                            return array;                        }                        next(',');                        white();                    }                }                error("Bad array");            },            object = function () {// Parse an object value.                var key,                    object = {};                if (ch === '{') {                    next('{');                    white();                    if (ch === '}') {                        next('}');                        return object;   // empty object                    }                    while (ch) {                        key = string();                        white();                        next(':');                        if (Object.hasOwnProperty.call(object, key)) {                            error('Duplicate key "' + key + '"');                        }                        object[key] = value();                        white();                        if (ch === '}') {                            next('}');                            return object;                        }                        next(',');                        white();                    }                }                error("Bad object");            };        value = function () {            // Parse a JSON value. It could be an object, an array, a string, a number,            // or a word.            white();            switch (ch) {                case '{':                    return object();                case '[':                    return array();                case '"':                    return string();                case '-':                    return number();                default:                    return ch >= '0' && ch <= '9' ? number() : word();            }        };        // Return the json_parse function. It will have access to all of the above        // functions and variables.        return function (source, reviver) {            var result;            text = source;            at = 0;            ch = ' ';            result = value();            white();            if (ch) {                error("Syntax error");            }            return typeof reviver === 'function' ?								function walk(holder, key) {								    var k, v, value = holder[key];								    if (value && typeof value === 'object') {								        for (k in value) {								            if (Object.hasOwnProperty.call(value, k)) {								                v = walk(value, k);								                if (v !== undefined) {								                    value[k] = v;								                } else {								                    delete value[k];								                }								            }								        }								    }								    return reviver.call(holder, key, value);								}({ '': result }, '') : result;        };    }());    window.hgJSonParse = json_parse;})(window);

 

文件下载区:

 

① P21第一段代码中的if语句有错,应该是if(typeof Object.create !== 'function')。英文版中统一使用的是Object.create,非修订版中统一使用的是Object.target,而修订版中只有这个地方判断的时候用的是Object.target,其他地方都是Object.create

转载于:https://www.cnblogs.com/hourglasser/p/3525695.html

你可能感兴趣的文章
开发者论坛一周精粹(第五十四期) 求购备案服务号1枚!
查看>>
validate表单验证及自定义方法
查看>>
javascript 中出现missing ) after argument list的错误
查看>>
使用Swagger2构建强大的RESTful API文档(2)(二十三)
查看>>
Docker容器启动报WARNING: IPv4 forwarding is disabled. Networking will not work
查看>>
(转)第三方支付参与者
查看>>
程序员修炼之道读后感2
查看>>
DWR实现服务器向客户端推送消息
查看>>
js中forEach的用法
查看>>
Docker之功能汇总
查看>>
!!a标签和button按钮只允许点击一次,防止重复提交
查看>>
(轉貼) Eclipse + CDT + MinGW 安裝方法 (C/C++) (gcc) (g++) (OS) (Windows)
查看>>
还原数据库
查看>>
作业调度框架 Quartz.NET 2.0 beta 发布
查看>>
mysql性能的检查和调优方法
查看>>
项目管理中的导向性
查看>>
Android WebView 学习
查看>>
(转)从给定的文本中,查找其中最长的重复子字符串的问题
查看>>
HDU 2159
查看>>
spring batch中用到的表
查看>>