namespace 信息采集系统.Common { /// <summary> /// Json类型对象,用于其它Json对象继承 /// </summary> /// <typeparam name="T">自定义类型</typeparam> [DataContract] public abstract class JsonObject<T> { /// <summary> /// 将Json对象转换为字节数组 /// </summary> /// <returns></returns> public byte[] ToArray() { var serializer = new DataContractJsonSerializer(this.GetType()); using (var ms = new MemoryStream()) { serializer.WriteObject(ms, this); var b = ms.ToArray(); return b; } } /// <summary> /// 将Json对象转换为字符串 /// </summary> /// <returns></returns> public override string ToString() { var b = this.ToArray(); var s = Encoding.UTF8.GetString(b); return s; } /// <summary> /// 将Json对象转换为字符串,并进行格式化输出 /// </summary> /// <returns>利于阅读的Json字符串</returns> public string ToFriendlyString() { return this.toFriendlyString(this, 0); } private string toFriendlyString(object obj, int level) { var sbAll = new StringBuilder(); var type = obj.GetType(); var interfaces = type.GetInterfaces(); if (interfaces.Contains(typeof(System.Collections.IList))) { var arr = obj as System.Collections.IList; var sbLine = new StringBuilder(); sbLine.Append($"\r\n{makeMultiSymbol(level)}[\r\n"); sbAll.Append(sbLine.ToString()); for (int i = 0; i < arr.Count; i++) { var item = arr[i]; string line = this.toFriendlyString(item, level + 1); sbAll.Append(line); if (i < arr.Count - 1) sbAll.Append(",\r\n"); else sbAll.Append("\r\n"); } sbLine = new StringBuilder(); sbLine.Append($"{makeMultiSymbol(level)}]"); sbAll.Append(sbLine.ToString()); } else { var sbLine = new StringBuilder(); sbLine.Append($"{makeMultiSymbol(level)}{{\r\n"); sbAll.Append(sbLine.ToString()); var dict = new Dictionary<int, string[]>(); var fields = type.GetFields(); for (int i = 0; i < fields.Length; i++) { var field = fields[i]; var atts = field.GetCustomAttributes(true); var att = atts.FirstOrDefault(x => x is DataMemberAttribute); if (att == null) continue; var order = (att as DataMemberAttribute).Order; var name = field.Name; var value = field.GetValue(obj); sbLine = new StringBuilder(); string strValue; if (value == null) strValue = "null"; else { var attrType = value.GetType(); if (attrType.IsEnum) strValue = ((int)value).ToString(); else if (attrType == typeof(string)) strValue = StringExt.ToCodeFormat(value as string); else if (attrType.IsValueType) strValue = value.ToString(); else strValue = this.toFriendlyString(value, level + 1); } if (dict.Values.Count(x => x[0] == name) == 0) { if (order == -1) order = GetNextOrderID(dict); dict.Add(order, new string[] { name, strValue }); } } var properties = type.GetProperties(); for (int i = 0; i < properties.Length; i++) { var property = properties[i]; var atts = property.GetCustomAttributes(true); var att = atts.FirstOrDefault(x => x is DataMemberAttribute); if (att == null) continue; var order = (att as DataMemberAttribute).Order; var name = property.Name; var value = property.GetValue(obj, null); sbLine = new StringBuilder(); string strValue; if (value == null) strValue = "null"; else { var attrType = value.GetType(); if (attrType.IsEnum) strValue = ((int)value).ToString(); else if (attrType == typeof(string)) strValue = StringExt.ToCodeFormat(value as string); else if (attrType.IsValueType) strValue = value.ToString(); else strValue = this.toFriendlyString(value, level + 1); } if (dict.Values.Count(x => x[0] == name) == 0) { if (order == -1) order = GetNextOrderID(dict); dict.Add(order, new string[] { name, strValue }); } } var kvs = dict.OrderBy(x => x.Key).ToArray(); for (int i = 0; i < kvs.Length; i++) { string line; var kv = kvs[i].Value; var name = kv[0]; var strValue = kv[1]; if (i < dict.Count - 1) line = $"{makeMultiSymbol(level + 1)}\"{name}\":{strValue},\r\n"; else line = $"{makeMultiSymbol(level + 1)}\"{name}\":{strValue}\r\n"; sbLine = new StringBuilder(); sbLine.Append(line); sbAll.Append(sbLine.ToString()); } sbLine = new StringBuilder(); sbLine.Append($"{makeMultiSymbol(level)}}}"); sbAll.Append(sbLine.ToString()); } var result = sbAll.ToString(); return result; } private string makeMultiSymbol(int count) { var symbol = "\t"; var sb = new StringBuilder(); for (int i = 0; i < count; i++) { sb.Append(symbol); } return sb.ToString(); } /// <summary> /// 字节数组转换为Json对象 /// </summary> /// <param name="b">字节数组</param> /// <returns>Json对象</returns> public static T From(byte[] b) { var serializer = new DataContractJsonSerializer(typeof(T)); using (var ms = new MemoryStream(b)) { var o = (T)serializer.ReadObject(ms); return o; } } /// <summary> /// 字符串转换为Json对象 /// </summary> /// <param name="s">字符串</param> /// <returns>Json对象</returns> public static T Parse(string s) { var b = Encoding.UTF8.GetBytes(s); var obj = From(b); return obj; } /// <summary> /// 将Json对象存储为文件 /// </summary> /// <param name="filePath">保存文件名</param> /// <param name="friendlyFormat"></param> public void Write(string filePath, bool friendlyFormat = false) { if (File.Exists(filePath)) File.Delete(filePath); if (friendlyFormat) { var s = this.ToFriendlyString(); File.WriteAllText(filePath, s); } else { var b = this.ToArray(); File.WriteAllBytes(filePath, b); } } /// <summary> /// 读取指定文件,加载Json对象 /// </summary> /// <param name="filePath">Json文件路径</param> /// <returns>Json对象</returns> public static T Read(string filePath) { var s = File.ReadAllText(filePath); var obj = JsonObject<T>.Parse(s); return obj; } /// <summary> /// 获取下一个可用的OrderID /// </summary> /// <param name="dict">临时存储节点的字典对象</param> /// <returns>下一个可用的OrderID</returns> public int GetNextOrderID(Dictionary<int, string[]> dict) { int order = 0; bool unused = false; while (!unused) { var exist = dict.Keys.Any(x => x == order); if (!exist) { unused = true; } else { order += 1; } } return order; } } /// <summary> /// 字符串扩展 /// </summary> public static class StringExt { /// <summary> /// 将字符串转换成带转义符的形式 /// </summary> /// <param name="s">输入字符串</param> /// <returns></returns> public static string ToCodeFormat(this string s) { s = s.Replace("\\", "\\\\"); s = s.Replace("\b", "\\b"); s = s.Replace("\f", "\\f"); s = s.Replace("\n", "\\n"); s = s.Replace("\r", "\\r"); s = s.Replace("\'", "\\'"); s = s.Replace("\"", "\\\""); s = s.Replace("\t", "\\t"); s = s.Replace("\0", "\\0"); s = s.Replace("\a", "\\a"); s = s.Replace("\v", "\\v"); return $"\"{s}\""; } } }