using Apewer; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; #if !NET20 using System.Dynamic; #endif using System.Reflection; using System.Text; namespace Apewer { /// Json。 [Serializable] public class Json { #region 配置。 [NonSerialized] private static bool _throw = false; [NonSerialized] private static bool _recursively = true; /// 允许产生 Exception,默认为不允许。 public static bool AllowException { get { return _throw; } set { _throw = value; } } /// 当存在递归引用时候包含递归项。指定为 True 时递归项为 Null 值,指定为 False 时不包含递归项。默认值:False。 public static bool AllowRecursively { get { return _recursively; } set { _recursively = value; } } #endregion #region 构造。 #region 基础。 [NonSerialized] private JToken _jtoken = null; [NonSerialized] private JArray _jarray = null; [NonSerialized] private JObject _jobject = null; [NonSerialized] private JProperty _jproperty = null; [NonSerialized] private JValue _jvalue = null; #endregion #region Reset /// 重置当前对象为空。 public void Reset() { Construct(); } /// 使用指定的文本重置当前对象。 public bool Reset(string json) { Construct(); if (json == null) { if (AllowException) throw new ArgumentNullException("json", "参数无效。"); return false; } var parsed = Parse(json); if (parsed == null) return false; Construct(parsed._jtoken); return true; } /// 使用指定的对象重置当前对象。 /// /// public bool Reset(Json json) { Construct(); if (json == null) { if (AllowException) throw new ArgumentNullException("json", "参数无效。"); return false; } var parsed = Parse(json.ToString()); if (parsed == null) return false; Construct(parsed._jtoken); return true; } /// 使用指定的字典对象重置当前对象。 /// /// public bool Reset(Dictionary dictionary) { Construct(); if (dictionary == null) { if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。"); return false; } var json = NewObject(); foreach (var item in dictionary) json[item.Key] = item.Value; Construct(json._jtoken); return true; } /// 使用指定的文本字典对象重置当前对象。 /// /// public bool Reset(TextSet dictionary) { Construct(); if (dictionary == null) { if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。"); return false; } return Reset(dictionary.Origin); } /// 使用指定的文本字典对象重置当前对象。 /// /// public bool Reset(ObjectSet dictionary) { Construct(); if (dictionary == null) { if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。"); return false; } return Reset(dictionary.Origin); } #endregion private void Construct(JToken jtoken = null) { _jtoken = jtoken; _jarray = null; _jobject = null; _jproperty = null; _jvalue = null; if (_jtoken != null) { if (_jtoken is JArray) _jarray = (JArray)_jtoken; if (_jtoken is JObject) _jobject = (JObject)_jtoken; if (_jtoken is JProperty) _jproperty = (JProperty)_jtoken; if (_jtoken is JValue) _jvalue = (JValue)_jtoken; } } private Json(JToken jtoken) { Construct(jtoken); } /// 创建 Json Object 实例。 public Json() { Construct(new JObject()); } #endregion #region 属性。 /// 用于兼容 SimpleJson 的操作。 public string this[string name] { get { var property = GetProperty(name); if (property == null) return ""; return property.ToString(); } set { SetProperty(name, value ?? ""); } } private JTokenType TokenType { get { if (_jtoken == null) return JTokenType.None; else return _jtoken.Type; //if (_jtoken == null) return 0; //switch (_jtoken.Type) //{ // case JTokenType.None: return 0; // case JTokenType.Object: return 1; // case JTokenType.Array: return 2; // case JTokenType.Constructor: return 3; // case JTokenType.Property: return 4; // case JTokenType.Comment: return 5; // case JTokenType.Integer: return 6; // case JTokenType.Float: return 7; // case JTokenType.String: return 8; // case JTokenType.Boolean: return 9; // case JTokenType.Null: return 10; // case JTokenType.Undefined: return 11; // case JTokenType.Date: return 12; // case JTokenType.Raw: return 13; // case JTokenType.Bytes: return 14; // case JTokenType.Guid: return 15; // case JTokenType.Uri: return 16; // case JTokenType.TimeSpan: return 17; // default: return 0; //} } } /// /// 获取当前实例的类型。可能的类型: /// None Object Array Constructor Property Comment Integer Float String /// Boolean Null Undefined Date Raw Bytes Guid Uri TimeSpan /// public string Type { get { return TokenType.ToString(); } } /// 实例有效。 public bool Available { get { return _jtoken != null && TokenType != JTokenType.None; } } /// 获取当前实例的值,当为 Json 格式时缩进。 public string Lucid { get { return ToString(true); } } /// 获取当前实例的值,当为 Json 格式时不缩进。 public string Text { get { return ToString(false); } } /// 当前实例类型为 Property 时,获取名称。 public string Name { get { return _jproperty == null ? null : _jproperty.Name; } } /// 获取值。 public object Value { get { if (_jvalue != null) { if (_jvalue.Value == null) return null; if (_jvalue.Value is JToken) return new Json((JToken)_jvalue.Value); else return _jvalue.Value; } if (_jproperty != null) { if (_jproperty.Value == null) return null; if (_jproperty.Value is JToken) return new Json((JToken)_jproperty.Value); else return _jproperty.Value; } return null; } } /// 实例无效。 public bool IsNull { get { return _jtoken == null; } } #endregion #region Private Get private List PrivateGetProperties { get { return GetProperties(); } } private List PrivateGetValues { get { return GetValues(); } } private List PrivateGetObjects { get { return GetObjects(); } } private List PrivateGetItems { get { return GetItems(); } } #endregion #region Object : Get/Set /// 获取所有类型为 Property 的子项。 public List GetProperties() { var list = new List(); if (_jobject != null) { var children = _jobject.Children(); foreach (var child in children) { var json = new Json(child); list.Add(json); } } return list; } /// 当前实例类型为 Object 时搜索属性,失败时返回 Null。 /// 将要搜索的属性名称,不可为 Null。 /// /// public Json GetProperty(string name) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return null; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return null; } var children = _jtoken.Children(); foreach (var child in children) { if (child.Name == name) { var json = new Json(child.Value); return json; } } return null; } /// 当前实例类型为 Object 时添加属性,值为 Null,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// /// public bool SetProperty(string name) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, null); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性。 /// /// /// public bool SetProperty(Json property) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (property == null) { if (_throw) throw new ArgumentNullException("property", "参数无效。"); return false; } if (property._jproperty == null || property.TokenType != JTokenType.Property) { if (_throw) throw new ArgumentException("property", "将要设置的属性无效。"); return false; } var name = property._jproperty.Name; var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, property._jtoken); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, bool value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, string value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, int value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, long value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, float value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, double value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// public bool SetProperty(string name, decimal value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } _jobject.Add(name, value); return true; } /// 当前实例类型为 Object 时添加属性,已存在的属性将被替换。 /// 将要添加的属性名称,不可为 Null。 /// 将要添加的属性值。 /// /// /// public bool SetProperty(string name, Json value) { if (_jobject == null || TokenType != JTokenType.Object) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (name == null) { if (_throw) throw new ArgumentNullException("name", "参数无效。"); return false; } var children = _jobject.Children(); foreach (var child in children) { if (child.Name == name) { _jobject.Remove(name); break; } } if (value == null) { _jobject.Add(name, null); } else { if (value._jtoken == null) { _jobject.Add(name, null); } else { _jobject.Add(name, value._jtoken); } } return true; } #endregion #region Array /// 获取所有类型为 Value 的子项。 public List GetValues() { var list = new List(); if (_jarray != null) { var children = _jarray.Children(); foreach (var child in children) { var json = new Json(child); list.Add(json); } } return list; } /// 获取所有类型为 Object 的子项。 public List GetObjects() { var list = new List(); if (_jarray != null) { var children = _jarray.Children(); foreach (var child in children) { var json = new Json(child); list.Add(json); } } return list; } /// 获取 Array 中的所有元素。 public List GetItems() { var list = new List(); if (_jarray != null) { var children = _jarray.Children(); foreach (var child in children) { var json = new Json(child); list.Add(json); } } return list; } /// 当前实例类型为 Array 时添加 Null 元素。 /// public bool AddItem() { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(JValue.CreateNull()); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(Json json) { if (json == null) { return AddItem(); } if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } if (json._jtoken == null || json.TokenType == JTokenType.None) { if (_throw) throw new ArgumentException("json", "将要设置的元素无效。"); return false; } _jarray.Add(json._jtoken); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(string value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value ?? ""); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(bool value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(int value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(long value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(float value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(double value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value); return true; } /// 当前实例类型为 Array 时添加元素。 /// 将要添加的元素。 /// public bool AddItem(decimal value) { if (_jarray == null || TokenType != JTokenType.Array) { if (_throw) throw new InvalidOperationException("当前实例不支持元素。"); return false; } _jarray.Add(value); return true; } /// 从 Parent 中移除。 /// /// public bool Remove() { if (_jtoken == null) return false; if (_jtoken.Parent == null) { if (_throw) throw new InvalidOperationException("Parent 对象丢失。"); return false; } try { _jtoken.Remove(); return true; } catch (Exception exception) { if (_throw) throw exception; return false; } } #endregion #region Property /// Json 对象实例为空。 public bool IsNone { get { return TokenType == JTokenType.None; } } /// Json 对象为 Object 实例。 public bool IsObject { get { return TokenType == JTokenType.Object; } } /// Json 对象为 Array 实例。 public bool IsArray { get { return TokenType == JTokenType.Array; } } /// Json 对象为 Property 实例。 public bool IsProperty { get { return TokenType == JTokenType.Property; } } /// Json 对象为 String 实例。 public bool IsString { get { return TokenType == JTokenType.String; } } /// 当前实例类型为 Property 时设置 Null 值。 /// public bool SetValue() { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = JValue.CreateNull(); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(Json value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } if (value == null) { _jproperty.Value = JValue.CreateNull(); return true; } if (value._jtoken == null || value.TokenType == JTokenType.None) { _jproperty.Value = JValue.CreateNull(); return true; } _jproperty.Value = new JValue(value._jtoken); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(string value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = value == null ? JValue.CreateNull() : JValue.CreateString(value); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(bool value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = new JValue(value); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(int value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = new JValue(value); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(long value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = new JValue(value); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(float value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = new JValue(value); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(double value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = new JValue(value); return true; } /// 当前实例类型为 Property 时设置值。 /// 将要设置的值。 /// public bool SetValue(decimal value) { var available = _jproperty != null && TokenType == JTokenType.Property; if (!available) { if (_throw) throw new InvalidOperationException("当前实例不支持属性。"); return false; } _jproperty.Value = new JValue(value); return true; } #endregion #region Import / Export #region From Text /// 从 String 到 Json 的隐式转换。 /// public static implicit operator Json(string text) { return Parse(text); } /// 解析文本为 Json 对象,失败时返回 Null。 /// public static Json Parse(string text) { try { var jtoken = JToken.Parse(text); var json = new Json(jtoken); return json; } catch (Exception exception) { if (AllowException) throw exception; return null; } } #endregion #region From Entity /// 解析实现 IList 的对象为 Json 对象,失败时返回 Null。 /// 将要解析的对象。 /// 在 Json 中将属性名称转换为小写。 /// 限制 Json 层级深度,当值小于零时将不限制深度。 /// 强制解析属性,忽略 Serializable 特性。 public static Json Parse(IList entity, bool lower = false, int depth = -1, bool force = false) { if (entity == null) return null; var recursive = new List(); recursive.Add(entity); return Parse(entity, lower, recursive, depth, force); } /// 解析实现 IDictionary 的对象为 Json 对象,失败时返回 Null。 /// 将要解析的对象。 /// 在 Json 中将属性名称转换为小写。 /// 限制 Json 层级深度,当值小于零时将不限制深度。 /// 强制解析属性,忽略 Serializable 特性。 public static Json Parse(IDictionary entity, bool lower = false, int depth = -1, bool force = false) { if (entity == null) return null; var recursive = new List(); recursive.Add(entity); return Parse(entity, lower, recursive, depth, force); } /// /// 解析对象为 Json 对象,包含所有公共属性,失败时返回 Null。 /// String 对象将解析文本;Json 对象将返回实例;String 对象将解析文本;实现 IDictionary 或 IList 的对象将解析内容。 /// /// 将要解析的对象。 /// 在 Json 中将属性名称转换为小写。 /// 限制 Json 层级深度,当值小于零时将不限制深度。 /// 强制解析属性,忽略 Serializable 特性。 /// public static Json Parse(object entity, bool lower = false, int depth = -1, bool force = false) { if (entity == null) return null; var recursive = new List(); recursive.Add(entity); return Parse(entity, lower, recursive, depth, force); } private static Json Parse(IList list, bool lower, List previous, int depth, bool force) { if (list == null) return null; if (list is IToJson) return ((IToJson)list).ToJson(); // IList 不再需要 SerializableAttribute 特性。 // { // var ltype = list.GetType(); // var sas = ltype.GetCustomAttributes(typeof(SerializableAttribute), false); // if (sas == null || sas.Length < 1) return null; // } var json = NewArray(); try { foreach (var item in list) { var value = item; // 检查递归引用。 var recursively = false; foreach (var r in previous) { if (ReferenceEquals(r, value)) { if (AllowRecursively) json.AddItem(); recursively = true; break; } } if (recursively) continue; // 处理 Type 对象。 if (value.GetType().Equals(typeof(Type)) && (previous.Count > 2)) { value = ((Type)value).FullName; } // 处理 Assembly 对象。 if (value.GetType().Equals(typeof(Assembly)) && (previous.Count > 2)) { value = ((Assembly)value).FullName; } if (value == null) { json.AddItem(); } else if (value is DateTime) { json.AddItem(value.ToString()); } else if (value is Boolean) { json.AddItem((Boolean)value); } else if (value is Int32) { json.AddItem((Int32)value); } else if (value is Int64) { json.AddItem((Int64)value); } else if (value is Single) { json.AddItem((Single)value); } else if (value is Double) { json.AddItem((Double)value); } else if (value is Decimal) { json.AddItem((Decimal)value); } else if (value is String) { json.AddItem((String)value); } else if (value is Json) { json.AddItem(value as Json); } else { if ((depth < 0) || (0 < depth && previous.Count < depth)) { var recursive = new List(); recursive.AddRange(previous); recursive.Add(value); if (value is IDictionary) { json.AddItem(Parse(value as IDictionary, lower, recursive, depth, force)); } else if (value is IList) { json.AddItem(Parse(value as IList, lower, recursive, depth, force)); } else { json.AddItem(Parse(value, lower, recursive, depth, force)); } } else { json.AddItem(value.ToString()); } } } } catch { } return json; } private static Json Parse(IDictionary dictionary, bool lower, List previous, int depth, bool force) { if (dictionary == null) return null; if (dictionary is IToJson) return ((IToJson)dictionary).ToJson(); // IDictionary 不再需要 SerializableAttribute 特性。 // { // var dtype = dictionary.GetType(); // var sas = dtype.GetCustomAttributes(typeof(SerializableAttribute), false); // if (sas == null || sas.Length < 1) return null; // } var json = NewObject(); try { var keys = dictionary.Keys; foreach (var key in keys) { try { var field = key.ToString(); if (lower && !string.IsNullOrEmpty(field)) field = field.ToLower(); var value = dictionary[key]; // 检查递归引用。 var recursively = false; foreach (var r in previous) { if (ReferenceEquals(r, value)) { if (AllowRecursively) json.SetProperty(field); recursively = true; break; } } if (recursively) continue; // 检查 System.Attribute.TypeId。 if (field == "TypeId" || field == "typeid") { if ((value != null) && (value is Type)) { json.SetProperty(field, ((Type)value).FullName); continue; } } // 处理 Type 对象。 if (value.GetType().Equals(typeof(Type)) && (previous.Count > 2)) { value = ((Type)value).FullName; } // 处理 Assembly 对象。 if (value.GetType().Equals(typeof(Assembly)) && (previous.Count > 2)) { value = ((Assembly)value).FullName; } if (value == null) { json.AddItem(); } else if (value is DateTime) { json.SetProperty(field, value.ToString()); } else if (value is Boolean) { json.SetProperty(field, (Boolean)value); } else if (value is Int32) { json.SetProperty(field, (Int32)value); } else if (value is Int64) { json.SetProperty(field, (Int64)value); } else if (value is Single) { json.SetProperty(field, (Single)value); } else if (value is Double) { json.SetProperty(field, (Double)value); } else if (value is Decimal) { json.SetProperty(field, (Decimal)value); } else if (value is String) { json.SetProperty(field, (String)value); } else if (value is Json) { json.SetProperty(field, value as Json); } else { if ((depth < 0) || (0 < depth && previous.Count < depth)) { var recursive = new List(); recursive.AddRange(previous); recursive.Add(value); if (value is IDictionary) { json.SetProperty(field, Parse(value as IDictionary, lower, recursive, depth, force)); } else if (value is IList) { json.SetProperty(field, Parse(value as IList, lower, recursive, depth, force)); } else { json.SetProperty(field, Parse(value, lower, recursive, depth, force)); } } else { json.SetProperty(field, value.ToString()); } } } catch { } } } catch { } return json; } private static Json Parse(object entity, bool lower, List previous, int depth, bool force) { if (entity == null) return null; if (entity is IToJson) return ((IToJson)entity).ToJson(); if (!force && !CanSerialize(entity.GetType(), false)) return null; var type = null as Type; try { type = entity.GetType(); } catch (Exception exception) { if (AllowException) throw exception; return null; } if (entity is Json) { if (lower) ToLower(entity as Json); return entity as Json; } else if (entity is String) { return Parse((String)entity, lower); } else if (entity is IDictionary) { return Parse(entity as IDictionary, (bool)lower); } else if (entity is IList) { return Parse(entity as IList, (bool)lower); } var independent = ClassUtility.ContainsAttribute(type); var properties = type.GetProperties(); if (properties.LongLength > 0L) { var dict = new Dictionary(); foreach (var property in properties) { var field = property.Name; if (field == null) continue; // 有 Independent 的对象不包含继承属性。 if (independent) { if (!property.DeclaringType.Equals(type)) continue; } // 处理 Assembly 对象的 DefinedTypes 和 ExportedTypes 属性。 if (entity is Assembly) { var assembly = entity as Assembly; if (assembly != null) { if (field == "DefinedTypes" || field == "ExportedTypes") { continue; } } } var getter = property.GetGetMethod(false); if (getter == null) continue; if (getter.IsStatic) continue; var value = null as object; try { value = getter.Invoke((object)entity, null); // 处理 Type 对象。 if (getter.ReturnType.Equals(typeof(Type)) && (previous.Count > 2)) { value = ((Type)value).FullName; } // 处理 Assembly 对象。 if (getter.ReturnType.Equals(typeof(Assembly)) && (previous.Count > 2)) { value = ((Assembly)value).FullName; } } catch (Exception ex) { value = ex.Message; } if (!dict.ContainsKey(field)) dict.Add(field, value); } var json = Parse(dict, lower, previous, depth, force); return json; } else { return NewObject(); } } #endregion #region To Text /// 导出文本,可指定缩进。若类型为 String,则导出 String 值,忽略缩进。 internal static string Export(Json json, bool indented) { if (json == null) return ""; if (json._jtoken == null) return ""; if (json.TokenType == JTokenType.String && json._jvalue != null) { return json._jvalue.Value.ToString(); } return json._jtoken.ToString(indented ? Formatting.Indented : Formatting.None); } /// 从 Json 到 String 的隐式转换,默认不缩进。 public static implicit operator string(Json json) { return Export(json, false); } /// 生成字符串,默认不缩进。若类型为 String,则导出 String 值。 public override string ToString() { return Export(this, false); } /// 生成字符串,可指定缩进。若类型为 String,则导出 String 值,忽略缩进。 public string ToString(bool indented) { return Export(this, indented); } #endregion #region To Entity /// 填充类型实例,失败时返回 NULL 值。 public static T FillObject(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false) where T : class, new() { if (json == null) return null; if (json._jtoken == null) return null; if (json.TokenType != JTokenType.Object) return null; var entity = Activator.CreateInstance(typeof(T)); FillObject(entity, json, ignoreCase, ignoreCharacters, force); return (T)entity; } /// 填充类型实例,失败时返回 NULL 值。 public static List FillArray(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false) where T : class, new() { if (json == null) return null; if (json._jtoken == null) return null; if (json.TokenType != JTokenType.Array) return null; var list = new List(); FillArray(list, json, ignoreCase, ignoreCharacters, force); return list; } private static void FillObject(object entity, Json json, bool ignoreCase, string ignoreCharacters, bool force) { if (entity == null) return; if (json == null) return; if (json.TokenType != JTokenType.Object) return; var jps = json.GetProperties(); if (jps.Count < 1) return; var etype = entity.GetType(); var eps = etype.GetProperties(); if (eps.Length < 1) return; foreach (var ep in eps) { foreach (var jp in jps) { var jpn = TextUtility.Trim(jp.Name); var epn = TextUtility.Trim(ep.Name); if (ignoreCharacters != null) { var characters = ignoreCharacters.ToCharArray(); foreach (var character in characters) { jpn.Replace(character.ToString(), ""); epn.Replace(character.ToString(), ""); } } if (ignoreCase) { if (jpn.Length > 0) jpn = jpn.ToLower(); if (epn.Length > 0) epn = epn.ToLower(); } if (jpn.Length < 1 || epn.Length < 1) continue; if (jpn != epn) continue; var value = jp.Value; if (value == null) continue; FillProperty(entity, ep, value, ignoreCase, ignoreCharacters, force); } } } private static void FillArray(object array, Json json, bool ignoreCase, string ignoreCharacters, bool force) { if (array == null) return; if (json == null) return; if (json.TokenType != JTokenType.Array) return; var type = array.GetType(); var subtypes = type.GetGenericArguments(); if (subtypes.Length < 1) return; var subtype = subtypes[0]; var methods = type.GetMethods(); var add = null as MethodInfo; foreach (var method in methods) { if (method.Name == "Add") { var parameters = method.GetParameters(); if (parameters.Length == 1) { if (parameters[0].ParameterType.FullName == subtype.FullName) { add = method; break; } } } } if (add == null) return; var jis = json.GetItems(); foreach (var ji in jis) { var parameter = new object[1] { null }; if (subtype.FullName == typeof(Json).FullName) { parameter[0] = ji; add.Invoke(array, parameter); } else { switch (subtype.FullName) { case "System.String": parameter[0] = (ji.TokenType == JTokenType.Null) ? null : ji.Text; add.Invoke(array, parameter); break; case "System.Int32": parameter[0] = TextUtility.GetInt32(ji.Text); add.Invoke(array, parameter); break; case "System.Int64": parameter[0] = TextUtility.GetInt64(ji.Text); add.Invoke(array, parameter); break; case "System.Double": parameter[0] = TextUtility.GetDouble(ji.Text); add.Invoke(array, parameter); break; case "System.Decimal": parameter[0] = TextUtility.GetDecimal(ji.Text); add.Invoke(array, parameter); break; default: var serializable = force ? true : CanSerialize(subtype, false); if (serializable && (ji is Json)) { switch (ji.TokenType) { case JTokenType.Object: var subobject = Activator.CreateInstance(subtype); FillObject(subobject, ji, ignoreCase, ignoreCharacters, force); parameter[0] = subobject; add.Invoke(array, parameter); break; case JTokenType.Array: var subarray = Activator.CreateInstance(subtype); FillArray(subarray, ji, ignoreCase, ignoreCharacters, force); parameter[0] = subarray; add.Invoke(array, parameter); break; } } break; } } } } private static void FillProperty(object entity, PropertyInfo property, object value, bool ignoreCase, string ignoreCharacters, bool force) { if (entity == null) return; if (property == null) return; if (value == null) return; var setter = property.GetSetMethod(); if (setter == null) return; var ptname = property.PropertyType.FullName; var parameter = new object[1] { null }; if (ptname == typeof(Json).FullName) { if (value is Json) { parameter[0] = value; setter.Invoke(entity, parameter); } } else { switch (ptname) { case "System.DateTime": try { parameter[0] = DateTime.Parse(value.ToString()); setter.Invoke(entity, parameter); } catch (Exception exception) { if (AllowException) throw exception; parameter[0] = TextUtility.EmptyString; setter.Invoke(entity, parameter); } break; case "System.String": if (value is Json) parameter[0] = ((Json)value).TokenType == JTokenType.Null ? null : ((Json)value).Text; else parameter[0] = value.ToString(); setter.Invoke(entity, parameter); break; case "System.Int32": parameter[0] = TextUtility.GetInt32(value.ToString()); setter.Invoke(entity, parameter); break; case "System.Int64": parameter[0] = TextUtility.GetInt64(value.ToString()); setter.Invoke(entity, parameter); break; case "System.Double": parameter[0] = TextUtility.GetDouble(value.ToString()); setter.Invoke(entity, parameter); break; case "System.Decimal": parameter[0] = TextUtility.GetDecimal(value.ToString()); setter.Invoke(entity, parameter); break; default: var serializable = force ? true : CanSerialize(property.PropertyType, false); if (serializable && (value is Json)) { switch (((Json)value).TokenType) { case JTokenType.Object: var subobject = Activator.CreateInstance(property.PropertyType); FillObject(subobject, (Json)value, ignoreCase, ignoreCharacters, force); parameter[0] = subobject; setter.Invoke(entity, parameter); break; case JTokenType.Array: var subarray = Activator.CreateInstance(property.PropertyType); FillArray(subarray, (Json)value, ignoreCase, ignoreCharacters, force); parameter[0] = subarray; setter.Invoke(entity, parameter); break; } } break; } } } #endregion #endregion #region Statics #region 创建实例。 /// 创建新对象。 public static Json NewObject() { return new Json(new JObject()); } /// 创建新对象。 public static Json NewObject(Dictionary dictionary) { var json = new Json(null); json.Reset(dictionary); return json; } /// 创建新对象。 public static Json NewObject(TextSet dictionary) { var json = new Json(null); json.Reset(dictionary); return json; } /// 创建新对象。 public static Json NewObject(ObjectSet dictionary) { var json = new Json(null); json.Reset(dictionary); return json; } /// 创建新对象。 public static Json NewArray() { return new Json(new JArray()); } /// 新建类型为 Property 的实例,值为 Null,失败时返回 Null。 /// Property 名称,不可为 Null。 /// public static Json NewProperty(string name) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, null)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, string value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, bool value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, int value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, long value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, float value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, double value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, decimal value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } return new Json(new JProperty(name, value)); } /// 新建类型为 Property 的实例,失败时返回 Null。 /// Property 名称,不可为 Null。 /// Property 值。 /// public static Json NewProperty(string name, Json value) { if (name == null) { if (AllowException) throw new ArgumentNullException("name", "参数无效。"); return null; } if (value == null) return new Json(new JProperty(name, null)); return new Json(new JProperty(name, null)); } #endregion /// 格式化 Json 文本。 public static string Format(string text) { if (text == null || text == "") return ""; try { var serializer = new Newtonsoft.Json.JsonSerializer(); var tr = (System.IO.TextReader)(new System.IO.StringReader(text)); var jtr = new Newtonsoft.Json.JsonTextReader(tr); var obj = serializer.Deserialize(jtr); if (obj != null) { var textWriter = new System.IO.StringWriter(); var jsonWriter = new Newtonsoft.Json.JsonTextWriter(textWriter) { Formatting = Newtonsoft.Json.Formatting.Indented, Indentation = 4, IndentChar = ' ' }; serializer.Serialize(jsonWriter, obj); return textWriter.ToString(); } else { return text; } } catch { return text ?? ""; } } /// 设置属性名称为小写。 public static Json ToLower(Json json) { if (json == null) return null; switch (json.TokenType) { case JTokenType.Array: var items = json.GetItems(); foreach (var i in items) ToLower(i); break; case JTokenType.Object: var properties = json.GetProperties(); foreach (var i in properties) { ToLower(i); var name = i._jproperty.Name; var value = i._jproperty.Value; if (!string.IsNullOrEmpty(name)) { var lower = name.ToLower(); if (name != lower) { i.Remove(); json._jobject.Add(lower, value); } } ToLower(new Json(value)); } break; } return json; } private static bool CanSerialize(Type type, bool inherit = false) { if (type == null) return false; var nsas = type.GetCustomAttributes(typeof(NonSerializedAttribute), inherit); if (nsas != null && nsas.Length > 0) return false; var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit); if (sas == null || sas.Length < 1) return false; return true; } #endregion } }