ZhiYeJianKang_PeiXun/cyqdata-master/Tool/JsonHelper.cs

1690 lines
61 KiB
C#
Raw Permalink Normal View History

2025-02-20 15:41:53 +08:00
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;
namespace CYQ.Data.Tool
{
/// <summary>
/// Escape json char options
/// <para>JsonHelper 的符号转义选项</para>
/// </summary>
public enum EscapeOp
{
/// <summary>
/// 过滤ascii小于32的特殊值、并对\n "(双引号)进行转义,对\转义符 (仅\\"或\\n时不转义其它情况转义
/// </summary>
Default,
/// <summary>
/// 不进行任何转义,只用于保留原如数据(注意:存在双引号时,[或ascii小于32的值都会破坏json格式]从而json数据无法被解析
/// </summary>
No,
/// <summary>
/// 过滤ascii小于32的特殊值、并对 \r \n \t "(双引号) \(转义符号) 直接进行转义
/// </summary>
Yes,
/// <summary>
/// 系统内部使用: ascii小于32包括\n \t \r、"(双引号)\(转义符号) 进行编码(规则为:@#{0}#@ {0}为asciii值系统转的时候会自动解码
/// </summary>
Encode
}
/// <summary>
/// Json class for you easy to operate json
/// <para>功能全面的json帮助类</para>
/// </summary>
public partial class JsonHelper
{
internal static EscapeOp DefaultEscape
{
get
{
return (EscapeOp)Enum.Parse(typeof(EscapeOp), AppConfig.JsonEscape);
}
}
#region
public JsonHelper()
{
}
/// <param name="addHead">with easyui header ?<para>是否带输出头</para></param>
public JsonHelper(bool addHead)
{
_AddHead = addHead;
}
/// <param name="addSchema">first row with table schema ?
/// <para>是否首行带表结构[MDataTable.LoadFromJson可以还原表的数据类型]</para></param>
public JsonHelper(bool addHead, bool addSchema)
{
_AddHead = addHead;
_AddSchema = addSchema;
}
#region
/// <summary>
/// Escape options
/// <para>转义符号</para>
/// </summary>
public EscapeOp Escape = JsonHelper.DefaultEscape;
/// <summary>
/// convert filed to lower
/// <para>是否将名称转为小写</para>
/// </summary>
public bool IsConvertNameToLower = false;
/// <summary>
/// formate datetime
/// <para>日期的格式化默认yyyy-MM-dd HH:mm:ss</para>
/// </summary>
public string DateTimeFormatter = "yyyy-MM-dd HH:mm:ss";
private const string brFlag = "[#<br>]";
RowOp _RowOp = RowOp.IgnoreNull;
/// <summary>
/// filter json data
/// <para>Json输出行数据的过滤选项</para>
/// </summary>
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;
/// <summary>
/// is success
/// <para>是否成功</para>
/// </summary>
public bool Success
{
get
{
return rowCount > 0;
}
}
private string errorMsg = "";
/// <summary>
/// Error message
/// <para>错误提示信息 </para>
/// </summary>
public string ErrorMsg
{
get
{
return errorMsg;
}
set
{
errorMsg = value;
}
}
private int rowCount = 0;
/// <summary>
/// data rows count
/// <para>当前返回的行数</para>
/// </summary>
public int RowCount
{
get
{
return rowCount;
}
set
{
rowCount = value;
}
}
private int total;
/// <summary>
/// totla count
/// <para>所有记录的总数(多数用于分页的记录总数)。</para>
/// </summary>
public int Total
{
get
{
if (total == 0)
{
return rowCount;
}
return total;
}
set
{
total = value;
}
}
#endregion
private List<string> jsonItems = new List<string>();
/// <summary>
/// flag a json is end and start a new json
/// <para> 添加完一个Json数据后调用此方法换行</para>
/// </summary>
public void AddBr()
{
jsonItems.Add(brFlag);
rowCount++;
}
StringBuilder headText = new StringBuilder();
StringBuilder footText = new StringBuilder();
/// <summary>
/// attach json data (AddHead must be true)
/// <para>添加底部数据只有AddHead为true情况才能添加数据</para>
/// </summary>
public void AddFoot(string name, string value)
{
AddFoot(name, value, false);
}
public void AddFoot(string name, string value, bool noQuotes)
{
if (_AddHead)
{
footText.Append("," + Format(name, value, noQuotes));
}
}
/// <summary>
/// add json key value
/// <para>添加一个字段的值</para>
/// </summary>
public void Add(string name, string value)
{
jsonItems.Add(Format(name, value, false));
}
/// <param name="noQuotes">value is no quotes
/// <para>值不带引号</para></param>
public void Add(string name, string value, bool noQuotes)
{
jsonItems.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)
{
value = (int)value;
Add(name, value.ToString(), true);
}
else
{
int groupID = DataType.GetGroup(DataType.GetSqlType(t));
bool noQuotes = groupID == 1 || groupID == 3;
if (groupID == 999)
{
v = ToJson(value);
}
else
{
v = Convert.ToString(value);
if (groupID == 3)
{
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);
}
return "\"" + name + "\":" + (!children ? "\"" : "") + value + (!children ? "\"" : "");//;//.Replace("\",\"", "\" , \"").Replace("}{", "} {").Replace("},{", "}, {")
}
/// <summary>
/// out json result
/// <para>输出Json字符串</para>
/// </summary>
public override string ToString()
{
int capacity = 100;
if (jsonItems.Count > 0)
{
capacity = jsonItems.Count * jsonItems[0].Length;
}
StringBuilder sb = new StringBuilder(capacity);
if (_AddHead)
{
if (headText.Length == 0)
{
sb.Append("{");
sb.Append("\"rowcount\":" + rowCount + ",");
sb.Append("\"total\":" + Total + ",");
sb.Append("\"errorMsg\":\"" + errorMsg + "\",");
sb.Append("\"success\":" + Success.ToString().ToLower() + ",");
sb.Append("\"rows\":");
}
else
{
sb.Append(headText.ToString());
}
}
if (jsonItems.Count == 0)
{
if (_AddHead)
{
sb.Append("[]");
}
}
else
{
if (jsonItems[jsonItems.Count - 1] != brFlag)
{
AddBr();
}
if (_AddHead || rowCount > 1)
{
sb.Append("[");
}
char left = '{', right = '}';
if (jsonItems[0] != brFlag && !jsonItems[0].Contains(":"))
{
//说明为数组
left = '[';
right = ']';
}
sb.Append(left);
int index = 0;
foreach (string val in jsonItems)
{
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 + ",");
if (index < jsonItems.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() + "}");
}
return sb.ToString();
//string json = sb.ToString();
//if (AppConfig.IsWeb && Escape == EscapeOp.Yes)
//{
// json = json.Replace("\n", "<br/>");
//}
//if (Escape != EscapeOp.No) // Web应用
//{
// json = json.Replace("\t", " ").Replace("\r", " ");
//}
//return json;
}
/// <param name="arrayEnd">end with [] ?</param>
/// <returns></returns>
public string ToString(bool arrayEnd)
{
string result = ToString();
if (arrayEnd && !result.StartsWith("["))
{
result = '[' + result + ']';
}
return result;
}
#endregion
/// <summary>
/// check string is json
/// <para>检测是否Json格式的字符串</para>
/// </summary>
public static bool IsJson(string json)
{
return JsonSplit.IsJson(json);
}
/// <param name="errIndex">the index of the error char
/// <para>错误的字符索引</para></param>
public static bool IsJson(string json, out int errIndex)
{
return JsonSplit.IsJson(json, out errIndex);
}
public static string GetValue(string json, string key)
{
return GetValue(json, key, DefaultEscape);
}
/// <summary>
/// Get json value
/// <para>获取Json字符串的值</para>
/// </summary>
/// <param name="key">the name or key of json
/// <para>键值(有层级时用XXX.YYY.ZZZ)</para></param>
/// <returns></returns>
public static string GetValue(string json, string key, EscapeOp op)
{
string value = GetSourceValue(json, key);
return UnEscape(value, op);
}
private static string GetSourceValue(string json, string key)
{
string result = string.Empty;
if (!string.IsNullOrEmpty(json))
{
List<Dictionary<string, string>> jsonList = JsonSplit.Split(json);
if (jsonList.Count > 0)
{
string[] items = key.Split('.');
string fKey = items[0];
int i = -1;
int fi = key.IndexOf('.');
if (int.TryParse(fKey, out i))//数字
{
if (i < jsonList.Count)
{
Dictionary<string, string> 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 // 非数字
{
Dictionary<string, string> jsonDic = jsonList[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;
}
/// <summary>
/// a easy method for you to return a json
/// <para>返回Json格式的结果信息</para>
/// </summary>
public static string OutResult(bool result, string msg)
{
return OutResult(result, msg, false);
}
/// <param name="noQuates">no ""</param>
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();
}
/// <summary>
/// split json to dicationary
/// <para>将Json分隔成键值对。</para>
/// </summary>
public static Dictionary<string, string> Split(string json)
{
if (!string.IsNullOrEmpty(json))
{
json = json.Trim();
if (json[0] != '{' && json[0] != '[')
{
json = ToJson(json);
}
List<Dictionary<string, string>> result = JsonSplit.Split(json);
if (result != null && result.Count > 0)
{
return result[0];
}
}
return null;
}
//public static List<Dictionary<string, string>> SplitArray(string jsonArray)
//{
// return SplitArray(jsonArray, DefaultEscape);
//}
/// <summary>
/// split json to dicationary array
/// <para>将Json 数组分隔成多个键值对。</para>
/// </summary>
public static List<Dictionary<string, string>> 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; }
}
/// <summary>
/// 解码替换数据转义符
/// </summary>
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<string> keys = new List<string>(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)
{
result = result.Replace("\\\\", "#&#=#");
if (op == EscapeOp.Yes)
{
result = result.Replace("\\t", "\t").Replace("\\r", "\r");
}
result = result.Replace("\\\"", "\"").Replace("\\n", "\n");//.Replace("\\\\","\\");
result = result.Replace("#&#=#", "\\");
}
return result;
}
}
// 扩展交互部分
public partial class JsonHelper
{
/// <summary>
/// 用于控制自循环的层级判断。
/// </summary>
internal int Level = 1;
/// <summary>
/// 用于自循环检测列表。
/// </summary>
internal MDictionary<int, int> LoopCheckList = new MDictionary<int, int>();
/// <summary>
/// Fill obj and get json from ToString() method
/// <para>从数据表中取数据填充,最终可输出json字符串</para>
/// </summary>
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]);
}
}
}
/// <summary>
/// Fill obj and get json from ToString() method
/// <para>从数据行中取数据填充,最终可输出json字符串</para>
/// </summary>
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();
int groupID = DataType.GetGroup(cell.Struct.SqlType);
bool noQuot = groupID == 1 || groupID == 3;
if (cell.IsNull)
{
value = "null";
noQuot = true;
}
else
{
if (groupID == 3 || (cell.Struct.MaxSize == 1 && groupID == 1)) // oracle 下的number 1会处理成bool类型
{
value = value.ToLower();
}
else if (groupID == 2)
{
DateTime dt;
if (DateTime.TryParse(value, out dt))
{
value = dt.ToString(DateTimeFormatter);
}
}
else if (groupID == 999)
{
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<T>
{
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<T,K>
{
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();
}
/// <summary>
/// 从数据结构填充最终可输出json字符串。
/// </summary>
/// <param name="column">数据结构</param>
/// <param name="isFullSchema">false输出单行的[列名:数据类型]true输出多行的完整的数据结构</param>
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("\"Columns\":");
}
foreach (MCellStruct item in column)
{
Add("ColumnName", item.ColumnName);
Add("SqlType", item.ValueType.FullName);
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
}
/// <summary>
/// Fill obj and get json from ToString() method
/// <para>可从类(对象,泛型List、泛型Dictionary中填充最终可输出json字符串。</para>
/// </summary>
/// <param name="obj">实体类对象</param>
public void Fill(object obj)
{
if (obj != null)
{
if (obj is String || obj is ValueType)
{
Fill(Convert.ToString(obj));
}
else if (obj is MDataTable)
{
Fill(obj as MDataTable);
}
else if (obj is MDataRow)
{
Fill(obj as MDataRow);
}
else if (obj is IEnumerable)
{
#region IEnumerable
Type t = obj.GetType();
int len = ReflectTool.GetArgumentLength(ref t);
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[0] == '{' || str[0] == '[') && JsonSplit.IsJson(str))
{
Fill(MDataRow.CreateFrom(o));
}
else
{
if (o is String) { SetEscape(ref str); }
jsonItems.Add("\"" + str + "\"");
}
}
else if (o is ValueType)
{
jsonItems.Add(o.ToString());
}
else
{
Fill(MDataRow.CreateFrom(o));
}
}
}
else if (len == 2)
{
Fill(MDataRow.CreateFrom(obj));
}
#endregion
}
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 DataColumnCollection)
{
MDataColumn mdc = obj as DataColumnCollection;
Fill(mdc, true);
}
else
{
MDataRow row = new MDataRow();
row.LoadFrom(obj);
Fill(row);
}
}
}
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, "");
}
}
}
}
}
private static Dictionary<string, object> lockList = new Dictionary<string, object>();
/// <summary>
/// 从Json字符串中反加载成数据表
/// </summary>
internal static MDataTable ToMDataTable(string jsonOrFileName, MDataColumn mdc, EscapeOp op)
{
MDataTable table = new MDataTable("SysDefaultLoadFromJson");
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<Dictionary<string, string>> result = SplitArray(json);
if (result != null && result.Count > 0)
{
#region
if (result.Count == 1)
{
#region
Dictionary<string, string> 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"];
}
result = SplitArray(dic["Columns"]);
}
#endregion
}
if (result != null && result.Count > 0)
{
Dictionary<string, string> 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<string, string> 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<string, string> 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<string, string> 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<string> 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;
}
/// <summary>
/// 将Json转换成集合
/// </summary>
/// <typeparam name="T">集合类型</typeparam>
/// <param name="json">json数据</param>
/// <returns></returns>
private static T ToIEnumerator<T>(string json, EscapeOp op)
where T : class
{
Type t = typeof(T);
if (t.FullName.StartsWith("System.Collections."))
{
Type[] ts;
int argLength = ReflectTool.GetArgumentLength(ref t, out ts);
#region Dictionary
if (t.FullName.Contains("Dictionary") && argLength == 2 && ts[0].Name == "String" && ts[1].Name == "String")
{
Dictionary<string, string> dic = Split(json);
return dic as T;
}
T objT = Activator.CreateInstance<T>();
Type oT = objT.GetType();
MethodInfo mi = null;
try
{
mi = oT.GetMethod("Add");
}
catch
{
}
if (mi == null)
{
mi = oT.GetMethod("Add", new Type[] { typeof(string), typeof(string) });
}
if (mi != null)
{
if (argLength == 1)
{
List<Dictionary<string, string>> items = JsonSplit.Split(json);
if (items != null && items.Count > 0)
{
foreach (Dictionary<string, string> item in items)
{
mi.Invoke(objT, new object[] { MDataRow.CreateFrom(item).ToEntity(ts[0]) });
}
}
}
else if (argLength == 2)
{
Dictionary<string, string> dic = Split(json);
if (dic != null && dic.Count > 0)
{
foreach (KeyValuePair<string, string> kv in dic)
{
mi.Invoke(objT, new object[] { Convert.ChangeType(kv.Key, ts[0]), Convert.ChangeType(UnEscape(kv.Value, op), ts[1]) });
}
}
}
return objT;
}
#endregion
}
else if (t.FullName.EndsWith("[]"))
{
Object o = new MDataRow().GetObj(t, json);
if (o != null)
{
return (T)o;
}
}
return default(T);
}
public static T ToEntity<T>(string json) where T : class
{
return ToEntity<T>(json, DefaultEscape);
}
/// <summary>
/// Convert json to Entity
/// <para>将Json转换为实体</para>
/// </summary>
/// <typeparam name="T">Type<para>类型</para></typeparam>
public static T ToEntity<T>(string json, EscapeOp op) where T : class
{
Type t = typeof(T);
if (t.FullName.StartsWith("System.Collections.") || t.FullName.EndsWith("[]"))
{
return ToIEnumerator<T>(json, op);
}
else
{
MDataRow row = new MDataRow(TableSchema.GetColumnByType(t));
row.LoadFrom(json, op);
return row.ToEntity<T>();
}
}
public static List<T> ToList<T>(string json) where T : class
{
return ToList<T>(json, DefaultEscape);
}
/// <summary>
/// Convert json to Entity List
/// <para>将Json转换为实体列表</para>
/// </summary>
/// <typeparam name="T">Type<para>类型</para></typeparam>
public static List<T> ToList<T>(string json, EscapeOp op) where T : class
{
return ToMDataTable(json, TableSchema.GetColumnByType(typeof(T)), op).ToList<T>();
}
/// <summary>
/// Convert object to json
/// <para>将一个对象实体泛型List字典Dictionary转成Json</para>
/// </summary>
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);
}
/// <param name="op">default value is RowOp.All
/// <para>默认值为RowOp.All</para></param>
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 MDataTable || obj is DataTable);
}
#region Xml Json
/// <summary>
/// 转Json
/// <param name="xml">xml字符串</param>
/// <param name="isConvertNameToLower">字段是否转小写</param>
/// <param name="isWithAttr">是否将属性值也输出</param>
/// </summary>
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
/// <summary>
/// Convert json to Xml
/// <para>将一个Json转成Xml</para>
/// </summary>
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);
}
/// <param name="isWithAttr">default value is true
/// <para>是否转成属性默认true</para></param>
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("<?xml version=\"1.0\" standalone=\"yes\"?>");
List<Dictionary<string, string>> 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"));//</root>";
}
xml.Append(GetXmlList(dicList, isWithAttr, op));
if (addRoot)
{
xml.Append(string.Format("</{0}>", rootName ?? "root"));//</root>";
}
}
return xml.ToString();
}
private static string GetXmlList(List<Dictionary<string, string>> 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<string, string> dic, bool isWithAttr, EscapeOp op)
{
StringBuilder xml = new StringBuilder();
bool isJson = false;
foreach (KeyValuePair<string, string> item in dic)
{
isJson = IsJson(item.Value);
if (!isJson)
{
xml.AppendFormat("<{0}>{1}</{0}>", 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<Dictionary<string, string>> 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("</{0}>", key);
}
}
else // 空Json {}
{
xml.AppendFormat("<{0}></{0}>", key);
}
if (item.Key.EndsWith("List") && isWithAttr)
{
xml.AppendFormat("</{0}>", item.Key);
}
}
}
return xml.ToString();
}
private static string GetXmlElement(string parentName, Dictionary<string, string> dic, EscapeOp op)
{
StringBuilder xml = new StringBuilder();
Dictionary<string, string> jsonDic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
xml.Append("<" + parentName);
foreach (KeyValuePair<string, string> 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<string, string> 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("</" + parentName + ">");
return xml.ToString();
}
private static string FormatCDATA(string text)
{
if (text.LastIndexOfAny(new char[] { '<', '>', '&' }) > -1 && !text.StartsWith("<![CDATA["))
{
text = "<![CDATA[" + text.Trim() + "]]>";
}
return text;
}
#endregion
}
public partial class JsonHelper
{
/// <summary>
/// 读取文本中的Json并去掉注释
/// </summary>
/// <returns></returns>
internal static string ReadJson(string filePath)
{
string json = string.Empty;
if (System.IO.File.Exists(filePath))
{
#region Read from path
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("\\\\", "\\");
}
}
#endregion
}
return json;
}
}
}