C# 对象转JSON,效率是系统自带的转化器的十倍,每次转换提供回调函数,可自定义转化结果,回调函数提供路径、属性和字段,可对转化的属性和字段进行特性查找,可对返回数据劫持。一般用于返回加密
public class ActionJson
{
public class CryptPath
{
public string Path { get; set; }
public int CryptType { get; set; }
public CryptPath()
{
this.CryptType = 1;
}
}
/// <summary>
/// 如果需要对路径进行加密,返回中添加对象 CryptPaths
/// 如果需要参数辅助加密,返回中添加对象CryptParams
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
public ActionResult Out(Func<object> func)
{
var jm = new JsonMessage();
var ret = default(object);
var json = string.Empty;
try
{
ret = func();
jm.Flag = true;
}
catch(Exception e)
{
if (e.InnerException != null)
jm.Message = e.InnerException.Message;
else
jm.Message = e.Message;
}
if (ret == null || jm.Flag == false)
{
jm.Data = null;
json = Serialize(jm,null,null);
}
else
{
var path = ret.GetType().GetProperty("CryptPaths")?.GetValue(ret);
var param = ret.GetType().GetProperty("CryptParams")?.GetValue(ret);
var paths = new List<string>();
if(path != null || param != null)
{
ret = ret.GetType().GetProperty("Data")?.GetValue(ret);
if (ret == null)
throw new Exception("必须用Data封装返回的数据");
}
if (path != null)
paths = ((IEnumerable<CryptPath>)path).Select<CryptPath, string>(o => o.Path).ToList();
json = Serialize(ret, param == null ? null : (object[])param, (_path, _val, _porf, _param) =>
{
return _val;
});
}
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Write(json);
HttpContext.Current.Response.End();
return new EmptyResult();
}
public static string Serialize(object obj, object[] cry, Func<string, object, object, object[], object> func = null)
{
return MakeObj(obj, "out", null, cry, func)?.ToString();
}
private static string ConvertString(object obj)
{
return obj.ToString().Replace("\r", "\\r").Replace("\n", "\\n").Replace("\"", "\\\"").Replace("\t", "\\t");
}
private static string ConvertDate(object obj)
{
return ((DateTime)obj).ToString("yyyy-MM-dd HH:mm:ss");
}
private static string MakeArr(string path, object obj, object[] cry, Func<string, object, object, object[], object> func)
{
var bremove = false;
var sb = new StringBuilder("[");
foreach (var item in (obj as System.Collections.IEnumerable))
{
bremove = true;
sb.Append($"{MakeObj(item, $"{path}.$", null, cry, func)},");
}
if (bremove)
sb = sb.Remove(sb.Length - 1, 1);
sb.Append("]");
return sb.ToString();
}
private static string MakeDict(string path, object obj, object[] cry, Func<string, object, object, object[], object> func)
{
var sb = new StringBuilder("{");
var bremove = false;
foreach (var item in (obj as System.Collections.IDictionary))
{
bremove = true;
var ikey = item.GetType().GetProperty("Key").GetValue(item, null);
var ival = item.GetType().GetProperty("Value").GetValue(item, null);
sb.Append($"\"{ikey}\":{ MakeObj(ival, $"{path}.{ikey}",null, cry, func)},");
}
if (bremove)
sb = sb.Remove(sb.Length - 1, 1);
bremove = false;
sb.Append("}");
return sb.ToString();
}
private static object MakeObj(object obj, string path,object fiopi, object[] cry, Func<string, object, object, object[], object> func = null)
{
if (obj is Int32? || obj is double? || obj is float? || obj is decimal?
|| obj is Boolean? || obj is short? || obj is Int16? || obj is Int64?)
{
if (func == null) return obj;
else return func(path, obj, fiopi, cry);
}
else if (obj is string || obj is char?)
{
if (func == null) return $"\"{ConvertString(obj)}\"";
else return func(path, $"\"{ConvertString(obj)}\"", fiopi, cry);
}
else if(obj is Boolean?)
{
if (func == null) return ((Boolean)obj) ? "true" : "false";
else return func(path, ((Boolean)obj) ? "true" : "false", fiopi, cry);
}
else if (obj is DateTime?)
{
if (func == null) return $"\"{ConvertDate(obj)}\"";
else return func(path, $"\"{ConvertDate(obj)}\"", fiopi, cry);
}
else if (obj == null || obj == DBNull.Value)
{
if (func == null) return "null";
else return func(path, "null", fiopi, cry);
}
else if (obj.GetType().IsEnum)
{
if (func == null) return (int)obj;
else return func(path, (int)obj, fiopi, cry);
}
else if (obj is System.Collections.IDictionary)
return MakeDict(path, obj, cry, func);
else if (obj is System.Collections.IEnumerable)
return MakeArr(path, obj, cry, func);
var sb = new StringBuilder("{");
foreach (var fi in obj.GetType().GetFields())
sb.AppendFormat("\"{0}\":{1},", fi.Name, MakeObj(fi.GetValue(obj), $"{path}.{fi.Name}", fi, cry, func));
foreach (var pi in obj.GetType().GetProperties())
sb.AppendFormat("\"{0}\":{1},", pi.Name, MakeObj(pi.GetValue(obj, null), $"{path}.{pi.Name}", pi, cry, func));
var ret = sb.ToString();
ret = ret.Remove(ret.Length - 1);
ret += "}";
return ret;
}
}