using System; using System.Collections.Generic; using System.Text; using System.Collections; using CYQ.Data.Table; using System.Data; using System.Text.RegularExpressions; using CYQ.Data.SQL; using System.IO; using System.Reflection; using CYQ.Data.Xml; using System.ComponentModel; using CYQ.Data.Tool; namespace CYQ.Data.Json { /// /// Json class for you easy to operate json /// 功能全面的json帮助类 /// public partial class JsonHelper { internal static EscapeOp DefaultEscape { get { return (EscapeOp)Enum.Parse(typeof(EscapeOp), AppConfig.Json.Escape); } } #region 实例属性 public JsonHelper() { } /// with easyui header ?是否带输出头 public JsonHelper(bool addHead) { _AddHead = addHead; } /// first row with table schema ? /// 是否首行带表结构[MDataTable.LoadFromJson可以还原表的数据类型] public JsonHelper(bool addHead, bool addSchema) { _AddHead = addHead; _AddSchema = addSchema; } #region 属性 /// /// Escape options /// 转义符号 /// public EscapeOp Escape = JsonHelper.DefaultEscape; /// /// convert filed to lower /// 是否将名称转为小写 /// public bool IsConvertNameToLower = false; /// /// convert enum to string /// 是否将枚举转字符串 /// public bool IsConvertEnumToString = false; /// /// convert enum to DescriptionAttribute /// 是否将枚举转属性描述 /// public bool IsConvertEnumToDescription = false; /// /// formate datetime /// 日期的格式化(默认:yyyy-MM-dd HH:mm:ss) /// public string DateTimeFormatter = "yyyy-MM-dd HH:mm:ss"; private const string brFlag = "[#
]"; RowOp _RowOp = RowOp.IgnoreNull; /// /// filter json data /// Json输出行数据的过滤选项 /// public RowOp RowOp { get { return _RowOp; } set { _RowOp = value; } } //internal BreakOp BreakOp //{ // get // { // switch (_RowOp) // { // case Table.RowOp.IgnoreNull: // return Table.BreakOp.Null; // default: // return Table.BreakOp.None; // } // } //} private bool _AddHead = false; private bool _AddSchema = false; /// /// is success /// 是否成功 /// public bool Success { get { return rowCount > 0; } } private string errorMsg = ""; /// /// Error message /// 错误提示信息 /// public string ErrorMsg { get { return errorMsg; } set { errorMsg = value; } } private int rowCount = 0; /// /// data rows count /// 当前返回的行数 /// public int RowCount { get { return rowCount; } set { rowCount = value; } } private int total; /// /// totla count /// 所有记录的总数(多数用于分页的记录总数)。 /// public int Total { get { if (total == 0) { return rowCount; } return total; } set { total = value; } } #endregion private List bodyItems = new List(128); private StringBuilder headText = new StringBuilder(); private StringBuilder footText = new StringBuilder(); /// /// flag a json is end and start a new json /// 添加完一个Json数据后调用此方法换行 /// public void AddBr() { bodyItems.Add(brFlag); rowCount++; } ///// ///// 调用后将替换默认的Head (AddHead must be true) ///// 添加底部数据(只有AddHead为true情况才能添加数据) ///// //public void AddHead(string name, string value) //{ // AddHead(name, value, false); //} //public void AddHead(string name, string value, bool noQuotes) //{ // if (_AddHead) // { // headText.Append(","); // headText.Append(Format(name, value, noQuotes)); // } //} /// /// attach json data (AddHead must be true) /// 添加底部数据(只有AddHead为true情况才能添加数据) /// public void AddFoot(string name, string value) { AddFoot(name, value, false); } public void AddFoot(string name, string value, bool noQuotes) { if (_AddHead) { footText.Append(","); footText.Append(Format(name, value, noQuotes)); } } /// /// add json key value /// 添加一个字段的值 /// public void Add(string name, string value) { bodyItems.Add(Format(name, value, false)); } /// value is no quotes /// 值不带引号 public void Add(string name, string value, bool noQuotes) { bodyItems.Add(Format(name, value, noQuotes)); } public void Add(string name, object value) { if (value != null) { string v = null; Type t = value.GetType(); if (t.IsEnum) { bool descriptionNoValue = true; if (IsConvertEnumToDescription) { FieldInfo field = t.GetField(value.ToString()); if (field != null) { DescriptionAttribute da = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (da != null) { Add(name, da.Description, false); descriptionNoValue = false; } } } if (descriptionNoValue) { if (IsConvertEnumToString) { Add(name, value.ToString(), false); } else { Add(name, ((int)value).ToString(), true); } } } else { DataGroupType group = DataType.GetGroup(DataType.GetSqlType(t)); bool noQuotes = group == DataGroupType.Number || group == DataGroupType.Bool; if (group == DataGroupType.Object) { v = ToJson(value); } else { v = Convert.ToString(value); if (group == DataGroupType.Bool) { v = v.ToLower(); } } Add(name, v, noQuotes); } } else { Add(name, "null", true); } } private string Format(string name, string value, bool children) { value = value ?? ""; children = children && !string.IsNullOrEmpty(value); if (!children && value.Length > 1 && ((value[0] == '{' && value[value.Length - 1] == '}') || (value[0] == '[' && value[value.Length - 1] == ']'))) { children = IsJson(value); } if (!children) { SetEscape(ref value); } StringBuilder sb = new StringBuilder(); sb.Append("\""); sb.Append(name); sb.Append("\":"); sb.Append(!children ? "\"" : ""); sb.Append(value); sb.Append(!children ? "\"" : ""); return sb.ToString(); //return "\"" + name + "\":" + (!children ? "\"" : "") + value + (!children ? "\"" : "");//;//.Replace("\",\"", "\" , \"").Replace("}{", "} {").Replace("},{", "}, {") } /// /// out json result /// 输出Json字符串 /// public override string ToString() { int capacity = 100; if (bodyItems.Count > 0) { capacity = bodyItems.Count * bodyItems[0].Length; } StringBuilder sb = new StringBuilder(capacity);// if (_AddHead) { if (headText.Length == 0) { sb.Append("{"); sb.Append("\"rowcount\":"); sb.Append(rowCount); sb.Append(","); sb.Append("\"total\":"); sb.Append(Total); sb.Append(","); sb.Append("\"errormsg\":\""); sb.Append(errorMsg); sb.Append("\","); sb.Append("\"success\":"); sb.Append(Success.ToString().ToLower()); sb.Append(","); sb.Append("\"rows\":"); } else { sb.Append(headText.ToString()); } } if (bodyItems.Count == 0) { if (_AddHead) { sb.Append("[]"); } } else { if (bodyItems[bodyItems.Count - 1] != brFlag) { AddBr(); } if (_AddHead || rowCount > 1) { sb.Append("["); } char left = '{', right = '}'; string[] items = bodyItems[0].Split(':'); if (bodyItems[0] != brFlag && (items.Length == 1 || !bodyItems[0].Trim('"').Contains("\""))) { //说明为数组 left = '['; right = ']'; } sb.Append(left); int index = 0; foreach (string val in bodyItems) { index++; if (val != brFlag) { sb.Append(val); sb.Append(","); } else { if (sb[sb.Length - 1] == ',') { sb.Remove(sb.Length - 1, 1);//性能优化(内部时,必须多了一个“,”号)。 // sb = sb.Replace(",", "", sb.Length - 1, 1); } sb.Append(right); sb.Append(","); if (index < bodyItems.Count) { sb.Append(left); } } } if (sb[sb.Length - 1] == ',') { sb.Remove(sb.Length - 1, 1); } //sb = sb.Replace(",", "", sb.Length - 1, 1);//去除最后一个,号。 //sb.Append("}"); if (_AddHead || rowCount > 1) { sb.Append("]"); } } if (_AddHead) { sb.Append(footText.ToString()); sb.Append("}"); } return sb.ToString(); //string json = sb.ToString(); //if (AppConfig.IsWeb && Escape == EscapeOp.Yes) //{ // json = json.Replace("\n", "
"); //} //if (Escape != EscapeOp.No) // Web应用 //{ // json = json.Replace("\t", " ").Replace("\r", " "); //} //return json; } /// end with [] ? /// public string ToString(bool arrayEnd) { string result = ToString(); if (arrayEnd && !result.StartsWith("[")) { result = '[' + result + ']'; } return result; } #endregion /// /// check string is json /// 检测是否Json格式的字符串 /// public static bool IsJson(string json) { return JsonSplit.IsJson(json, true); } /// the index of the error char /// 错误的字符索引 public static bool IsJson(string json, out int errIndex) { return JsonSplit.IsJson(json, true, out errIndex); } public static T GetValue(string json, string key) { string v = GetValue(json, key); return ConvertTool.ChangeType(v); } public static T GetValue(string json, string key, EscapeOp op) { string v = GetValue(json, key, op); return ConvertTool.ChangeType(v); } public static string GetValue(string json, string key) { return GetValue(json, key, DefaultEscape); } /// /// Get json value /// 获取Json字符串的值 /// /// the name or key of json /// 键值(有层级时用:XXX.YYY.ZZZ) /// public static string GetValue(string json, string key, EscapeOp op) { string value = GetSourceValue(json, key); return UnEscape(value, op); } /// /// Json 返回值是否为true(包含"success":true) /// /// /// public static bool IsSuccess(string json) { return GetValue(json, "success"); } private static string GetSourceValue(string json, string key) { string result = string.Empty; if (!string.IsNullOrEmpty(json)) { Dictionary jsonDic = Split(json);//先取top1 if (jsonDic != null && jsonDic.Count > 0 && jsonDic.ContainsKey(key)) { return jsonDic[key]; } string[] items = key.Split('.'); string fKey = items[0]; int i = -1; int fi = key.IndexOf('.'); if (int.TryParse(fKey, out i))//数字 { List> jsonList = JsonSplit.Split(json, i + 1); if (i < jsonList.Count) { Dictionary numJson = jsonList[i]; if (items.Length == 1) { result = ToJson(numJson); } else if (items.Length == 2) // 0.xxx { string sKey = items[1]; if (numJson.ContainsKey(sKey)) { result = numJson[sKey]; } } else { return GetSourceValue(ToJson(numJson), key.Substring(fi + 1)); } } } else // 非数字 { if (jsonDic != null && jsonDic.Count > 0) { if (items.Length == 1) { if (jsonDic.ContainsKey(fKey)) { result = jsonDic[fKey]; } } else if (jsonDic.ContainsKey(fKey)) // 取子集 { return GetSourceValue(jsonDic[fKey], key.Substring(fi + 1)); } } } } return result; } /// /// a easy method for you to return a json /// 返回Json格式的结果信息 /// public static string OutResult(bool result, string msg) { return OutResult(result, msg, false); } /// no "" public static string OutResult(bool result, string msg, bool noQuates) { JsonHelper js = new JsonHelper(false, false); js.Add("success", result.ToString().ToLower(), true); js.Add("msg", msg, noQuates); return js.ToString(); } public static string OutResult(bool result, object msgObj) { return OutResult(result, msgObj, null, null); } public static string OutResult(bool result, object msgObj, string name, object value, params object[] nameValues) { //JsonHelper js = new JsonHelper(false, false); //js.Add("success", result.ToString().ToLower(), true); //if (msgObj is string) //{ // js.Add("msg", Convert.ToString(msgObj)); //} //else //{ // js.Add("msg", ToJson(msgObj), true); //} int num = name == null ? 2 : 4; object[] nvs = new object[nameValues.Length + num]; nvs[0] = "msg"; nvs[1] = msgObj; if (num == 4) { nvs[2] = name; nvs[3] = value; } if (nameValues.Length > 0) { nameValues.CopyTo(nvs, num); } return OutResult("success", result, nvs); } public static string OutResult(string name, object value, params object[] nameValues) { JsonHelper js = new JsonHelper(); js.Add(name, value); for (int i = 0; i < nameValues.Length; i++) // 1 { if (i % 2 == 0) { string k = Convert.ToString(nameValues[i]); i++; object v = i == nameValues.Length ? null : nameValues[i]; js.Add(k, v); } } return js.ToString(); } /// /// split json to dicationary /// 将Json分隔成键值对。 /// public static Dictionary Split(string json) { if (!string.IsNullOrEmpty(json)) { json = json.Trim(); if (json[0] != '{' && json[0] != '[') { json = ToJson(json); } List> result = JsonSplit.Split(json, 1); if (result != null && result.Count > 0) { return result[0]; } } return new Dictionary(StringComparer.OrdinalIgnoreCase); } //public static List> SplitArray(string jsonArray) //{ // return SplitArray(jsonArray, DefaultEscape); //} /// /// split json to dicationary array /// 将Json 数组分隔成多个键值对。 /// public static List> SplitArray(string jsonArray) { if (string.IsNullOrEmpty(jsonArray)) { return null; } jsonArray = jsonArray.Trim(); return JsonSplit.Split(jsonArray); } private void SetEscape(ref string value) { if (Escape == EscapeOp.No) { return; } bool isInsert = false; int len = value.Length; StringBuilder sb = new StringBuilder(len + 10); for (int i = 0; i < len; i++) { char c = value[i]; if (Escape == EscapeOp.Encode) { if (c < 32 || c == '"' || c == '\\') { sb.AppendFormat("@#{0}#@", (int)c); isInsert = true; } else { sb.Append(c); } continue; } if (c < 32) { #region 十六进制符号处理 switch (c) { case '\n': sb.Append("\\n");//直接替换追加。 break; case '\t': if (Escape == EscapeOp.Yes) { sb.Append("\\t");//直接替换追加 } break; case '\r': if (Escape == EscapeOp.Yes) { sb.Append("\\r");//直接替换追加 } break; default: break; } #endregion // '\n'=10 '\r'=13 '\t'=9 都会被过滤。 isInsert = true; continue; } #region 双引号和转义符号处理 switch (c) { case '"': isInsert = true; sb.Append("\\"); //if (i == 0 || value[i - 1] != '\\')//这个是强制转,不然整体格式有问题。 //{ // isInsert = true; // sb.Append("\\"); //} break; case '\\': //if (i < len - 1) //{ // switch (value[i + 1]) // { // // case '"': // case 'n': // case 'r'://r和t要转义,不过出事。 // case 't': // isInsert = true; // sb.Append("\\"); // break; // default: // //isOK = true; // break; // } //} bool isOK = Escape == EscapeOp.Yes;// || (i != 0 && i == len - 1 && value[i - 1] != '\\');// 如果是以\结尾,(非\\结尾时, 这部分是强制转,不会然影响整体格式) if (!isOK && Escape == EscapeOp.Default && len > 1 && i < len - 1)//中间 { switch (value[i + 1]) { // case '"': case 'n': //case 'r'://r和t要转义,不过出事。 //case 't': break; default: isOK = true; break; } } if (isOK) { isInsert = true; sb.Append("\\"); } break; } #endregion sb.Append(c); } if (isInsert) { value = null; value = sb.ToString(); } else { sb = null; } } /// /// 解码替换数据转义符 /// public static string UnEscape(string result, EscapeOp op) { if (op == EscapeOp.No) { return result; } if (op == EscapeOp.Encode) { if (result.IndexOf("@#") > -1 && result.IndexOf("#@") > -1) // 先解系统编码 { MatchCollection matchs = Regex.Matches(result, @"@#(\d{1,2})#@", RegexOptions.Compiled); if (matchs != null && matchs.Count > 0) { List keys = new List(matchs.Count); foreach (Match match in matchs) { if (match.Groups.Count > 1) { int code = int.Parse(match.Groups[1].Value); string charText = ((char)code).ToString(); result = result.Replace(match.Groups[0].Value, charText); } } } } return result; } if (result.IndexOf("\\") > -1) { bool has = result.IndexOf("\\\\") > -1; if (has) { result = result.Replace("\\\\", "#&#=#"); } if (op == EscapeOp.Yes) { result = result.Replace("\\t", "\t").Replace("\\r", "\r"); } result = result.Replace("\\\"", "\"").Replace("\\n", "\n");//.Replace("\\\\","\\"); if (has) { result = result.Replace("#&#=#", "\\"); } } return result; } } // 扩展交互部分 public partial class JsonHelper { /// /// 用于控制自循环的层级判断。 /// internal int Level = 1; /// /// 用于自循环检测列表。 /// internal MDictionary LoopCheckList = new MDictionary(); /// /// Fill obj and get json from ToString() method /// 从数据表中取数据填充,最终可输出json字符串 /// public void Fill(MDataTable table) { if (table == null) { ErrorMsg = "MDataTable object is null"; return; } if (_AddSchema) { Fill(table.Columns, false); } //RowCount = table.Rows.Count; Total = table.RecordsAffected; if (table.Rows.Count > 0) { for (int i = 0; i < table.Rows.Count; i++) { Fill(table.Rows[i]); } } } /// /// Fill obj and get json from ToString() method /// 从数据行中取数据填充,最终可输出json字符串 /// public void Fill(MDataRow row) { if (row == null) { ErrorMsg = "MDataRow object is null"; return; } for (int i = 0; i < row.Count; i++) { MDataCell cell = row[i]; if (cell.IsJsonIgnore) { continue; } if (_RowOp == RowOp.None || (!cell.IsNull && (cell.Struct.IsPrimaryKey || cell.State >= (int)_RowOp))) { #region MyRegion string name = row[i].ColumnName; if (IsConvertNameToLower) { name = name.ToLower(); } string value = cell.ToString(); DataGroupType group = DataType.GetGroup(cell.Struct.SqlType); bool noQuot = group == DataGroupType.Number || group == DataGroupType.Bool; if (cell.IsNull) { value = "null"; noQuot = true; } else { if (group == DataGroupType.Bool || (cell.Struct.MaxSize == 1 && group == DataGroupType.Number)) // oracle 下的number 1会处理成bool类型 { value = value.ToLower(); } else if (group == DataGroupType.Date) { DateTime dt; if (DateTime.TryParse(value, out dt)) { value = dt.ToString(DateTimeFormatter); } } else if (group == DataGroupType.Object) { int hash = cell.Value.GetHashCode(); //检测是否循环引用 if (LoopCheckList.ContainsKey(hash)) { //continue; int level = LoopCheckList[hash]; if (level < Level) { continue; } else { LoopCheckList[hash] = Level;//更新级别 } } else { LoopCheckList.Add(hash, Level); } Type t = cell.Struct.ValueType; if (t.FullName == "System.Object") { t = cell.Value.GetType(); } if (t.Name == "Byte[]") { value = Convert.ToBase64String(cell.Value as byte[]); } else if (t.Name == "String") { value = cell.StringValue; } else { if (cell.Value is IEnumerable) { int len = ReflectTool.GetArgumentLength(ref t); if (len <= 1)//List { JsonHelper js = new JsonHelper(false, false); js.Level = Level + 1; js.LoopCheckList = LoopCheckList; js.Escape = Escape; js._RowOp = _RowOp; js.DateTimeFormatter = DateTimeFormatter; js.IsConvertNameToLower = IsConvertNameToLower; if (cell.Value is MDataRowCollection) { MDataTable dtx = (MDataRowCollection)cell.Value; js.Fill(dtx); } else { js.Fill(cell.Value); } value = js.ToString(true); noQuot = true; } else if (len == 2)//Dictionary { MDataRow dicRow = MDataRow.CreateFrom(cell.Value); dicRow.DynamicData = LoopCheckList; value = dicRow.ToJson(RowOp, IsConvertNameToLower, Escape); noQuot = true; } } else { if (!t.FullName.StartsWith("System."))//普通对象。 { MDataRow oRow = new MDataRow(TableSchema.GetColumnByType(t)); oRow.DynamicData = LoopCheckList; oRow.LoadFrom(cell.Value); value = oRow.ToJson(RowOp, IsConvertNameToLower, Escape); noQuot = true; } else if (t.FullName == "System.Data.DataTable") { MDataTable dt = cell.Value as DataTable; dt.DynamicData = LoopCheckList; value = dt.ToJson(false, false, RowOp, IsConvertNameToLower, Escape); noQuot = true; } } } } } Add(name, value, noQuot); #endregion } } AddBr(); } /// /// 从数据结构填充,最终可输出json字符串。 /// /// 数据结构 /// false:输出单行的[列名:数据类型];true:输出多行的完整的数据结构 public void Fill(MDataColumn column, bool isFullSchema) { if (column == null) { ErrorMsg = "MDataColumn object is null"; return; } if (isFullSchema) { if (!string.IsNullOrEmpty(column.TableName)) { _AddHead = true; headText.Append("{"); headText.Append("\"TableName\":\"" + column.TableName + "\","); headText.Append("\"Description\":\"" + column.Description + "\","); headText.Append("\"RelationTables\":\"" + string.Join(",", column.RelationTables.ToArray()) + "\","); headText.Append("\"Columns\":"); } foreach (MCellStruct item in column) { Add("ColumnName", item.ColumnName); Add("SqlType", item.ValueType.FullName); Add("SqlTypeName", item.SqlTypeName); Add("IsAutoIncrement", item.IsAutoIncrement.ToString().ToLower(), true); Add("IsCanNull", item.IsCanNull.ToString().ToLower(), true); Add("MaxSize", item.MaxSize.ToString(), true); Add("Scale", item.Scale.ToString().ToLower(), true); Add("IsPrimaryKey", item.IsPrimaryKey.ToString().ToLower(), true); Add("DefaultValue", Convert.ToString(item.DefaultValue)); Add("Description", item.Description); //新增属性 Add("TableName", item.TableName); Add("IsUniqueKey", item.IsUniqueKey.ToString().ToLower(), true); Add("IsForeignKey", item.IsForeignKey.ToString().ToLower(), true); Add("FKTableName", item.FKTableName); AddBr(); } } else { for (int i = 0; i < column.Count; i++) { Add(column[i].ColumnName, column[i].ValueType.FullName); } AddBr(); } rowCount = 0;//重置为0 } /// /// Fill obj and get json from ToString() method /// 可从类(对象,泛型List、泛型Dictionary)中填充,最终可输出json字符串。 /// /// 实体类对象 public void Fill(object obj) { if (obj != null) { if (obj is String || obj is ValueType) { Fill(Convert.ToString(obj)); } else if (obj is DataTable) { MDataTable dt = obj as DataTable; Fill(dt); } else if (obj is DataRow) { MDataRow row = obj as DataRow; Fill(row); } else if (obj is MDataTable) { Fill(obj as MDataTable); } else if (obj is MDataRow) { Fill(obj as MDataRow); } else if (obj is DataRowCollection) { MDataTable dt = (MDataRowCollection)obj; Fill(dt); } else if (obj is MDataRowCollection) { MDataTable dt = (MDataRowCollection)obj; Fill(dt); } else if (obj is DataColumnCollection) { MDataColumn mdc = obj as DataColumnCollection; Fill(mdc, true); } else if (obj is Dictionary) { Fill(obj as Dictionary);//避开转Row,提升性能 } else if (obj is MDictionary) { Fill(obj as MDictionary);//避开转Row,提升性能 } else if (obj is Dictionary) { Fill(obj as Dictionary);//避开转Row,提升性能 } else if (obj is MDictionary) { Fill(obj as MDictionary);//避开转Row,提升性能 } else if (obj is IEnumerable) { #region IEnumerable Type t = obj.GetType(); Type[] argTypes; int len = ReflectTool.GetArgumentLength(ref t, out argTypes); if (len == 1) { foreach (object o in obj as IEnumerable) { if (o is MDataTable) { Fill(o as MDataTable); } else if (o is DataTable) { MDataTable dt = o as DataTable; Fill(dt); } else if (o is String || o is DateTime || o is Enum || o is Guid) { string str = o.ToString(); if (str.Length > 0 && (str[0] == '{' || str[0] == '[') && JsonSplit.IsJson(str)) { Fill(MDataRow.CreateFrom(o)); } else { if (o is String) { SetEscape(ref str); } bodyItems.Add("\"" + str + "\""); } } else if (o is ValueType) { bodyItems.Add(o.ToString()); } else if (o is MDataRow) { Fill(o as MDataRow); } else { Type listType = argTypes[0]; if (ReflectTool.GetSystemType(ref listType) == SysType.Custom) { FillEntity(o); } else { Fill(MDataRow.CreateFrom(o));//直接优化成实体。 } } } } else if (len == 2) { if (t.Name.StartsWith("MDictionary") && argTypes[0].Name == "String") { List items = t.GetMethod("GetKeys").Invoke(obj, new object[0]) as List; IEnumerable values = t.GetMethod("GetValues").Invoke(obj, new object[0]) as IEnumerable; int i = 0; foreach (object value in values) { Add(items[i], value); i++; } //MethodInfo methodGet = t.GetMethod("Get"); //foreach (var item in items) //{ // Add(item, methodGet.Invoke(obj, new object[] { item })); //} } else if (t.Name.StartsWith("Dictionary") && argTypes[0].Name == "String") { IEnumerable keys = t.GetProperty("Keys").GetValue(obj, null) as IEnumerable; IEnumerable values = t.GetProperty("Values").GetValue(obj, null) as IEnumerable; List items = new List(); foreach (string key in keys) { items.Add(key); } int i = 0; foreach (object value in values) { Add(items[i], value); i++; } } else { Fill(MDataRow.CreateFrom(obj, t)); } } #endregion } else { FillEntity(obj); } } } public void Fill(string query) { if (!string.IsNullOrEmpty(query)) { query = query.Trim('?'); string[] items = query.Split('&'); foreach (string item in items) { if (!string.IsNullOrEmpty(item)) { int index = item.IndexOf('='); if (index > -1) { Add(item.Substring(0, index), item.Substring(index + 1, item.Length - index - 1)); } else { Add(item, ""); } } } } } public void Fill(Dictionary dic) { foreach (var item in dic) { Add(item.Key, item.Value); } } public void Fill(MDictionary dic) { List items = dic.GetKeys(); foreach (var item in items) { Add(item, dic[item]); } } public void Fill(Dictionary dic) { foreach (var item in dic) { Add(item.Key, item.Value); } } public void Fill(MDictionary dic) { List items = dic.GetKeys(); foreach (var item in items) { Add(item, dic[item]); } } /// /// 加载实体 /// /// private void FillEntity(object entity) { Type t = entity.GetType(); List pList = ReflectTool.GetPropertyList(t); if (pList.Count > 0) { foreach (PropertyInfo item in pList) { SetJson(entity, item, null); } } List fList = ReflectTool.GetFieldList(t); if (fList.Count > 0) { foreach (FieldInfo item in fList) { SetJson(entity, null, item); } } AddBr(); } private void SetJson(object entity, PropertyInfo pi, FieldInfo fi) { if (ReflectTool.ExistsAttr(AppConst.JsonIgnoreType, pi, fi))//获取Json忽略标识 { return;//被Json忽略的列,不在返回列结构中。 } string name = pi != null ? pi.Name : fi.Name; object objValue = pi != null ? pi.GetValue(entity, null) : fi.GetValue(entity); Type type = pi != null ? pi.PropertyType : fi.FieldType; string dateFormat = DateTimeFormatter; if (type.IsEnum) { if (ReflectTool.ExistsAttr(AppConst.JsonEnumToStringType, pi, fi)) { objValue = objValue.ToString(); type = typeof(String); } else if (ReflectTool.ExistsAttr(AppConst.JsonEnumToDescriptionType, pi, fi)) { FieldInfo field = type.GetField(objValue.ToString()); if (field != null) { DescriptionAttribute da = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (da != null) { objValue = da.Description; type = typeof(String); } } } else { objValue = (int)objValue; } } else if (type.FullName.Contains("System.DateTime") && ReflectTool.ExistsAttr(AppConst.JsonFormatType, pi, fi)) { JsonFormatAttribute jf = ReflectTool.GetAttr(pi, fi); if (jf != null) { dateFormat = jf.DatetimeFormat; } } SetNameValue(name, objValue, type, dateFormat); } private void SetNameValue(string name, object objValue, Type valueType, string dateFormat) { if (IsConvertNameToLower) { name = name.ToLower(); } string value = null; bool noQuot = false; if (objValue == null || objValue == DBNull.Value) { if (_RowOp == Table.RowOp.IgnoreNull) { return; } value = "null"; noQuot = true; } else { if (valueType.FullName == "System.Object") { valueType = objValue.GetType();//定位到指定类型。 } value = Convert.ToString(objValue); DataGroupType group = DataType.GetGroup(DataType.GetSqlType(valueType)); noQuot = group == DataGroupType.Number || group == DataGroupType.Bool; #region 处理非Null的情况 if (group == DataGroupType.Bool) // oracle 下的number 1会处理成bool类型 { value = value.ToLower(); } else if (group == DataGroupType.Date) { DateTime dt; if (DateTime.TryParse(value, out dt)) { value = dt.ToString(dateFormat); } } else if (group == DataGroupType.Object) { #region 处理对象及循环引用。 int hash = objValue.GetHashCode(); //检测是否循环引用 if (LoopCheckList.ContainsKey(hash)) { //continue; int level = LoopCheckList[hash]; if (level < Level) { return; } else { LoopCheckList[hash] = Level;//更新级别 } } else { LoopCheckList.Add(hash, Level); } if (valueType.Name == "Byte[]") { value = Convert.ToBase64String(objValue as byte[]); } else { JsonHelper js = new JsonHelper(false, false); js.Level = Level + 1; js.LoopCheckList = LoopCheckList; js.Escape = Escape; js._RowOp = _RowOp; js.DateTimeFormatter = dateFormat; js.IsConvertNameToLower = IsConvertNameToLower; js.Fill(objValue); value = js.ToString(objValue is IList || objValue is MDataTable || objValue is DataTable); noQuot = true; //if (objValue is IEnumerable) //{ // int len = ReflectTool.GetArgumentLength(ref valueType); // if (len <= 1)//List // { // JsonHelper js = new JsonHelper(false, false); // js.Level = Level + 1; // js.LoopCheckList = LoopCheckList; // js.Escape = Escape; // js._RowOp = _RowOp; // js.DateTimeFormatter = dateFormat; // js.IsConvertNameToLower = IsConvertNameToLower; // if (objValue is MDataRowCollection) // { // MDataTable dtx = (MDataRowCollection)objValue; // js.Fill(dtx); // } // else // { // js.Fill(objValue); // } // value = js.ToString(true); // noQuot = true; // } // else if (len == 2)//Dictionary // { // MDataRow dicRow = MDataRow.CreateFrom(objValue); // dicRow.DynamicData = LoopCheckList; // value = dicRow.ToJson(RowOp, IsConvertNameToLower, Escape); // noQuot = true; // } //} //else //{ // if (!valueType.FullName.StartsWith("System."))//普通对象。 // { // MDataRow oRow = new MDataRow(TableSchema.GetColumnByType(valueType)); // oRow.DynamicData = LoopCheckList; // oRow.LoadFrom(objValue); // value = oRow.ToJson(RowOp, IsConvertNameToLower, Escape); // noQuot = true; // } // else if (valueType.FullName == "System.Data.DataTable") // { // MDataTable dt = objValue as DataTable; // dt.DynamicData = LoopCheckList; // value = dt.ToJson(false, false, RowOp, IsConvertNameToLower, Escape); // noQuot = true; // } //} } #endregion } #endregion } Add(name, value, noQuot); } private static Dictionary lockList = new Dictionary(); /// /// 从Json字符串中反加载成数据表 /// internal static MDataTable ToMDataTable(string jsonOrFileName, MDataColumn mdc, EscapeOp op) { MDataTable table = new MDataTable(); if (mdc != null) { table.Columns = mdc; } if (string.IsNullOrEmpty(jsonOrFileName)) { return table; } else { jsonOrFileName = jsonOrFileName.Trim(); } try { #region 读取Json string json = string.Empty; #region 获取Json字符串 if (!jsonOrFileName.StartsWith("{") && !jsonOrFileName.StartsWith("["))//读取文件。 { if (System.IO.File.Exists(jsonOrFileName)) { table.TableName = Path.GetFileNameWithoutExtension(jsonOrFileName); if (table.Columns.Count == 0) { table.Columns = MDataColumn.CreateFrom(jsonOrFileName, false); } json = IOHelper.ReadAllText(jsonOrFileName).Trim(',', ' ', '\r', '\n'); } } else { json = jsonOrFileName; } if (json.StartsWith("{")) { json = '[' + json + ']'; } #endregion List> result = SplitArray(json); if (result != null && result.Count > 0) { #region 加载数据 if (result.Count == 1) { #region 自定义输出头判断 Dictionary dic = result[0]; if (dic.ContainsKey("total") && dic.ContainsKey("rows")) { int count = 0; if (int.TryParse(dic["total"], out count)) { table.RecordsAffected = count;//还原记录总数。 } result = SplitArray(dic["rows"]); } else if (dic.ContainsKey("TableName") && dic.ContainsKey("Columns")) { table.TableName = dic["TableName"]; if (dic.ContainsKey("Description")) { table.Description = dic["Description"]; } if (dic.ContainsKey("RelationTables")) { table.Columns.AddRelateionTableName(dic["RelationTables"]); } result = SplitArray(dic["Columns"]); } #endregion } if (result != null && result.Count > 0) { Dictionary keyValueDic = null; for (int i = 0; i < result.Count; i++) { keyValueDic = result[i]; if (i == 0) { #region 首行列头检测 bool addColumn = table.Columns.Count == 0; bool isContinue = false; int k = 0; foreach (KeyValuePair item in keyValueDic) { if (k == 0 && item.Value.StartsWith("System.")) { isContinue = true; } if (!addColumn) { break; } if (!table.Columns.Contains(item.Key)) { SqlDbType type = SqlDbType.NVarChar; if (isContinue && item.Value.StartsWith("System."))//首行是表结构 { type = DataType.GetSqlType(item.Value.Replace("System.", string.Empty)); } table.Columns.Add(item.Key, type, (k == 0 && type == SqlDbType.Int)); if (k > keyValueDic.Count - 3 && type == SqlDbType.DateTime) { table.Columns[k].DefaultValue = SqlValue.GetDate; } } k++; } if (isContinue) { continue; } #endregion } bool isKeyValue = table.Columns.Count == 2 && table.Columns[1].ColumnName == "Value" && (table.Columns[0].ColumnName == "Key" || table.Columns[0].ColumnName == "Name"); if (isKeyValue) { foreach (KeyValuePair item in keyValueDic) { MDataRow row = table.NewRow(true); row.Set(0, item.Key); row.Set(1, item.Value); } } else { MDataRow row = table.NewRow(true); MDataCell cell = null; foreach (KeyValuePair item in keyValueDic) { cell = row[item.Key]; if (cell == null && mdc == null) { table.Columns.Add(item.Key, SqlDbType.NVarChar); cell = row[item.Key]; } if (cell != null) { string val = UnEscape(item.Value, op); cell.Value = val; cell.State = 1; } } } } } #endregion } else { List items = JsonSplit.SplitEscapeArray(json); if (items != null && items.Count > 0) { if (mdc == null) { table.Columns.Add("Key"); } foreach (string item in items) { table.NewRow(true).Set(0, item.Trim('"', '\'')); } } } #endregion } catch (Exception err) { Log.Write(err, LogType.Error); } return table; } /// /// 将Json转换成集合 /// /// 集合类型 /// json数据 /// /// private static T ToIEnumerator(string json, EscapeOp op) where T : class { return ToIEnumerator(typeof(T), json, op) as T; } private static object ToIEnumerator(Type t, string json, EscapeOp op) { if (t.FullName.StartsWith("System.Collections.") || t.FullName.Contains("MDictionary") || t.FullName.Contains("MList")) { Type[] ts; int argLength = ReflectTool.GetArgumentLength(ref t, out ts); if (argLength == 1) { return JsonSplit.ToEntityOrList(t, json, op); } else { #region Dictionary if (t.Name.StartsWith("Dictionary") && ts[0].Name == "String" && ts[1].Name == "String") { //忽略MDictionary return Split(json); } object objT = t.Name.Contains("Dictionary") ? Activator.CreateInstance(t, StringComparer.OrdinalIgnoreCase) : Activator.CreateInstance(t); Type oT = objT.GetType(); MethodInfo mi = null; try { if (t.Name == "NameValueCollection") { mi = oT.GetMethod("Add", new Type[] { typeof(string), typeof(string) }); } else { mi = oT.GetMethod("Add"); } } catch { } if (mi == null) { mi = oT.GetMethod("Add", new Type[] { typeof(string), typeof(string) }); } if (mi != null) { Dictionary dic = Split(json); if (dic != null && dic.Count > 0) { foreach (KeyValuePair kv in dic) { mi.Invoke(objT, new object[] { ConvertTool.ChangeType(kv.Key, ts[0]), ConvertTool.ChangeType(UnEscape(kv.Value, op), ts[1]) }); } } return objT; } #endregion } } else if (t.FullName.EndsWith("[]")) { return new MDataRow().GetObj(t, json); } return null; } public static T ToEntity(string json) where T : class { return ToEntity(json, DefaultEscape); } internal static object ToEntity(Type t, string json, EscapeOp op) { if (t.FullName == "System.Data.DataTable") { return MDataTable.CreateFrom(json, null, op).ToDataTable(); } if (t.Name == "MDataTable") { return MDataTable.CreateFrom(json, null, op); } if (t.FullName.StartsWith("System.Collections.") || t.FullName.EndsWith("[]") || t.FullName.Contains("MDictionary") || t.FullName.Contains("MList")) { return ToIEnumerator(t, json, op); } else { return JsonSplit.ToEntityOrList(t, json, op); } } /// /// Convert json to Entity /// 将Json转换为实体 /// /// Type类型 public static T ToEntity(string json, EscapeOp op) where T : class { Type t = typeof(T); if (t.FullName == "System.Data.DataTable") { object dt = MDataTable.CreateFrom(json, null, op).ToDataTable(); return (T)dt; } if (t.Name == "MDataTable") { object mdt = MDataTable.CreateFrom(json, null, op); return (T)mdt; } if (t.FullName.StartsWith("System.Collections.") || t.FullName.EndsWith("[]") || t.FullName.Contains("MDictionary") || t.FullName.Contains("MList")) { return ToIEnumerator(json, op); } else { return JsonSplit.ToEntity(json, op); } } public static List ToList(string json)// where T : class { return ToList(json, DefaultEscape); } /// /// Convert json to Entity List /// 将Json转换为实体列表 /// /// Type类型 public static List ToList(string json, EscapeOp op)// where T : class { return JsonSplit.ToList(json, 0, op);//减少中间转换环节。 } /// /// Convert object to json /// 将一个对象(实体,泛型List,字典Dictionary)转成Json /// public static string ToJson(object obj) { return ToJson(obj, false, RowOp.IgnoreNull); } public static string ToJson(object obj, bool isConvertNameToLower) { return ToJson(obj, isConvertNameToLower, RowOp.IgnoreNull); } public static string ToJson(object obj, bool isConvertNameToLower, RowOp rowOp) { return ToJson(obj, isConvertNameToLower, rowOp, DefaultEscape); } /// default value is RowOp.All /// 默认值为RowOp.All public static string ToJson(object obj, bool isConvertNameToLower, RowOp rowOp, EscapeOp escapeOp) { string text = Convert.ToString(obj); if (text == "") { return "{}"; } else if (text[0] == '{' || text[0] == '[') { if (IsJson(text)) { return text; } } else if (text[0] == '<' && text[text.Length - 1] == '>') { return XmlToJson(text, true); } JsonHelper js = new JsonHelper(); js.LoopCheckList.Add(obj.GetHashCode(), 0); js.Escape = escapeOp; js.IsConvertNameToLower = isConvertNameToLower; js.RowOp = rowOp; js.Fill(obj); return js.ToString(obj is IList || obj is DataTable || obj is MDataTable); } } public partial class JsonHelper { #region Xml 转 Json /// /// 转Json /// xml字符串 /// 是否将属性值也输出 /// private static string XmlToJson(string xml, bool isWithAttr) { using (XHtmlAction action = new XHtmlAction(false, true)) { try { action.LoadXml(xml); return action.ToJson(action.XmlDoc.DocumentElement, isWithAttr); } catch (Exception err) { Log.WriteLogToTxt(err, LogType.Error); return string.Empty; } } } #endregion #region Json 转 Xml /// /// Convert json to Xml /// 将一个Json转成Xml /// public static string ToXml(string json) { return ToXml(json, true); } public static string ToXml(string json, bool isWithAttr) { return ToXml(json, isWithAttr, DefaultEscape); } public static string ToXml(string json, bool isWithAttr, EscapeOp op) { return ToXml(json, isWithAttr, op, null); } /// default value is true /// 是否转成属性,默认true public static string ToXml(string json, bool isWithAttr, EscapeOp op, string rootName) { if (!string.IsNullOrEmpty(rootName)) { json = string.Format("{{\"{0}\":{1}}}", rootName, json); } StringBuilder xml = new StringBuilder(); xml.Append(""); List> dicList = JsonSplit.Split(json); if (dicList != null && dicList.Count > 0) { bool addRoot = dicList.Count > 1 || dicList[0].Count > 1; if (addRoot) { xml.Append(string.Format("<{0}>", rootName ?? "root"));//"; } xml.Append(GetXmlList(dicList, isWithAttr, op)); if (addRoot) { xml.Append(string.Format("", rootName ?? "root"));//"; } } return xml.ToString(); } private static string GetXmlList(List> dicList, bool isWithAttr, EscapeOp op) { if (dicList == null || dicList.Count == 0) { return string.Empty; } StringBuilder xml = new StringBuilder(); for (int i = 0; i < dicList.Count; i++) { xml.Append(GetXml(dicList[i], isWithAttr, op)); } return xml.ToString(); } private static string GetXml(Dictionary dic, bool isWithAttr, EscapeOp op) { StringBuilder xml = new StringBuilder(); bool isJson = false; foreach (KeyValuePair item in dic) { isJson = IsJson(item.Value); if (!isJson) { xml.AppendFormat("<{0}>{1}", item.Key, FormatCDATA(UnEscape(item.Value, op))); } else { string key = item.Key; if (key.EndsWith("List") && isWithAttr) { xml.AppendFormat("<{0}>", key); key = key.Substring(0, key.Length - 4); } List> jsonList = JsonSplit.Split(item.Value); if (jsonList != null && jsonList.Count > 0) { if (!isWithAttr) { xml.AppendFormat("<{0}>", item.Key); } for (int j = 0; j < jsonList.Count; j++) { if (isWithAttr) { xml.Append(GetXmlElement(key, jsonList[j], op)); } else { xml.Append(GetXml(jsonList[j], isWithAttr, op)); } } if (!isWithAttr) { xml.AppendFormat("", key); } } else // 空Json {} { xml.AppendFormat("<{0}>", key); } if (item.Key.EndsWith("List") && isWithAttr) { xml.AppendFormat("", item.Key); } } } return xml.ToString(); } private static string GetXmlElement(string parentName, Dictionary dic, EscapeOp op) { StringBuilder xml = new StringBuilder(); Dictionary jsonDic = new Dictionary(StringComparer.OrdinalIgnoreCase); xml.Append("<" + parentName); foreach (KeyValuePair kv in dic) { if (kv.Value.IndexOf('"') > -1 || kv.Value.Length > 50 || kv.Key.Contains("Remark") || kv.Key.Contains("Description") || kv.Key.Contains("Rule") || IsJson(kv.Value)) // 属性不能带双引号,所以转到元素处理。 { jsonDic.Add(kv.Key, kv.Value); } } //InnerText 节点存在=》(如果有元素节点,则当属性处理;若无,则当InnerText) bool useForInnerText = dic.ContainsKey(parentName) && jsonDic.Count == 0; foreach (KeyValuePair kv in dic) { if (!jsonDic.ContainsKey(kv.Key) && (kv.Key != parentName || !useForInnerText)) { xml.AppendFormat(" {0}=\"{1}\"", kv.Key, kv.Value);//先忽略同名属性,内部InnerText节点, } } xml.Append(">"); if (useForInnerText) { xml.Append(FormatCDATA(UnEscape(dic[parentName], op)));//InnerText。 } else if (jsonDic.Count > 0) { xml.Append(GetXml(jsonDic, true, op));//数组,当元素处理。 } xml.Append(""); return xml.ToString(); } private static string FormatCDATA(string text) { if (text.LastIndexOfAny(new char[] { '<', '>', '&' }) > -1 && !text.StartsWith(""; } return text; } #endregion } public partial class JsonHelper { /// /// 读取文本中的Json(并去掉注释) /// /// internal static string ReadJson(string filePath) { string json = IOHelper.ReadAllText(filePath); if (!string.IsNullOrEmpty(json)) { int index = json.LastIndexOf("/*"); if (index > -1)//去掉注释 { json = Regex.Replace(json, @"/\*[^:][.\s\S]*?\*/", string.Empty, RegexOptions.IgnoreCase); } char splitChar = '\n'; if (json.IndexOf(splitChar) > -1) { string[] items = json.Split(splitChar); StringBuilder sb = new StringBuilder(); foreach (string item in items) { if (!item.TrimStart(' ', '\r', '\t').StartsWith("//")) { sb.Append(item.Trim(' ', '\r', '\t')); } } json = sb.ToString(); } if (json.IndexOf("\\\\") > -1) { json = json.Replace("\\\\", "\\"); } } return json; } } }