『练手』手写一个独立Json算法 JsonHelper
背景:
> 一直使用 Newtonsoft.Json.dll 也算挺稳定的。
> 但这个框架也挺闹心的:
> 1、影响编译失败:https://www.cnblogs.com/zihuxinyu/archive/2013/05/06/3063181.html (我也经常遇到)
> 2、WinCE版本(小众用户)太大:Newtonsoft.Json.Compact.dll 352kb
> 3、自己写一个微型框架,在通讯方面 要用到Json:一个 100k 的框架,引用一个 400k 的 Newtonsoft.Json.dll —— 总感觉 尾大不掉。
>4、不知道 目标类型,我只想将 Json反序列化成 List 和 Hash 的结构 —— 传说中的 万能结构,Newtonsoft.Json.dll 支持得不友好。
于是一咬牙,花 9个小时,手写了一个 Json算法:
> 基本支持 Newtonsoft.Json.dll 的 一切正反Json序列化:对象(字典)、集合、元数据。
> 可以将任意 Json 转换成 List 和 Hash 的 组合结构。
> 性能只有 Newtonsoft.Json.dll 的 1/3 (超长Json反序列化, JsonHelper:10000次/秒,Newtonsoft.Json.dll 性能是 30000次/秒)。
> 性能我已经满意了,源码 和 性能截图 如下。
性能测试截图:
超长Json反序列化:
JsonHelper 性能为 10W次 12.7秒,Newtonsoft.Json.dll 性能为 10W次 3.7秒。
手写一个嵌套实体 10W次 反序列化性能:
JsonHelper 性能为 10W次 7.8秒,Newtonsoft.Json.dll 性能为 10W次 1.3秒。
手写一个嵌套实体 10W次 序列化:
JsonHelper 性能为 10W次 2.6秒,Newtonsoft.Json.dll 性能为 10W次 1.2秒。
JsonHelper 源码:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Collections.Specialized; 5 using System.Globalization; 6 using System.IO; 7 using System.Linq; 8 using System.Reflection; 9 using System.Text; 10 using System.Text.RegularExpressions; 11 using Newtonsoft.Json.Linq; 12 13 namespace InkFx.Utils 14 { 15 /// <summary> 16 /// 不依赖 任何第三方JSON框架的 Json 辅助类 17 /// </summary> 18 public static class JsonHelper 19 { 20 #region 公 共 函 数 21 22 /// <summary> 23 /// 将指定对象转换成 JSON 24 /// </summary> 25 public static string JsonSerialize(object data) 26 { 27 return JsonSerialize(data, false); 28 } 29 /// <summary> 30 /// 将指定对象转换成 JSON 31 /// </summary> 32 public static string JsonSerialize(object data, bool throwEeception) 33 { 34 if (data == null) return "null"; 35 36 try 37 { 38 JsonObject obj = ObjectToJsonObject(data); 39 return obj == null ? "null" : obj.ToJson(); 40 } 41 catch (Exception exp) 42 { 43 if (throwEeception) throw; 44 else 45 { 46 string logMsg = "JsonHelper.JsonSerialize(object data) 序列化错误:" + exp; 47 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 48 return null; 49 } 50 } 51 } 52 53 54 55 /// <summary> 56 /// 将JSON 转换成 指定类型对象 57 /// </summary> 58 public static T JsonDeserialize<T>(string json) 59 { 60 return JsonDeserialize<T>(json, false); 61 } 62 /// <summary> 63 /// 将JSON 转换成 指定类型对象 64 /// </summary> 65 public static T JsonDeserialize<T>(string json, bool throwEeception) 66 { 67 if (IsNullOrWhiteSpace(json)) return default(T); 68 69 try 70 { 71 JsonObject obj = StringToJsonObject(json); 72 T result = JsonObjectToObject<T>(obj); 73 return (T)result; 74 } 75 catch (Exception exp) 76 { 77 if (throwEeception) throw; 78 else 79 { 80 string logMsg = "JsonHelper.JsonDeserialize<T>(string json) 反序列化错误:" + exp; 81 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 82 return default(T); 83 } 84 } 85 } 86 /// <summary> 87 /// 将JSON 转换成 指定类型对象 88 /// </summary> 89 public static object JsonDeserialize(string json, Type type) 90 { 91 return JsonDeserialize(json, type, false); 92 } 93 /// <summary> 94 /// 将JSON 转换成 指定类型对象 95 /// </summary> 96 public static object JsonDeserialize(string json, Type type, bool throwEeception) 97 { 98 if (IsNullOrWhiteSpace(json)) return null; 99 100 try 101 { 102 JsonObject obj = StringToJsonObject(json); 103 object result = JsonObjectToObject(obj, type); 104 return result; 105 } 106 catch (Exception exp) 107 { 108 if (throwEeception) throw; 109 else 110 { 111 string logMsg = "JsonHelper.JsonDeserialize(string json, Type type) 反序列化错误:" + exp; 112 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 113 return null; 114 } 115 } 116 } 117 118 119 /// <summary> 120 /// 在 未指定 Json 反序列化类型 的情况下, 用 JsonObject 表达一个 Json对象 121 /// </summary> 122 public static JsonObject JsonDeserializeObject(string json) 123 { 124 return JsonDeserializeObject(json, false); 125 } 126 /// <summary> 127 /// 在 未指定 Json 反序列化类型 的情况下, 用 JsonObject 表达一个 Json对象 128 /// </summary> 129 public static JsonObject JsonDeserializeObject(string json, bool throwEeception) 130 { 131 if (IsNullOrWhiteSpace(json)) return null; 132 133 try 134 { 135 JsonObject result = StringToJsonObject(json); 136 return result; 137 } 138 catch (Exception exp) 139 { 140 if (throwEeception) throw; 141 else 142 { 143 string logMsg = "JsonHelper.JsonDeserializeObject(string json) 反序列化错误:" + exp; 144 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 145 return null; 146 } 147 } 148 } 149 /// <summary> 150 /// 在 未指定 Json 反序列化类型 的情况下, 用 字典、集合 表达一个 Json对象 151 /// </summary> 152 public static object JsonDeserializeHasnList(string json) 153 { 154 return JsonDeserializeHasnList<Hashtable>(json, false); 155 } 156 /// <summary> 157 /// 在 未指定 Json 反序列化类型 的情况下, 用 字典、集合 表达一个 Json对象 158 /// </summary> 159 public static object JsonDeserializeHasnList(string json, bool throwEeception) 160 { 161 return JsonDeserializeHasnList<Hashtable>(json, throwEeception); 162 } 163 /// <summary> 164 /// 在 未指定 Json 反序列化类型 的情况下, 用 字典、集合 表达一个 Json对象 165 /// </summary> 166 public static object JsonDeserializeHasnList<HashT>(string json) where HashT : IDictionary, new() 167 { 168 return JsonDeserializeHasnList<HashT>(json, false); 169 } 170 /// <summary> 171 /// 在 未指定 Json 反序列化类型 的情况下, 用 字典、集合 表达一个 Json对象 172 /// </summary> 173 public static object JsonDeserializeHasnList<HashT>(string json, bool throwEeception) where HashT : IDictionary, new() 174 { 175 if (IsNullOrWhiteSpace(json)) return null; 176 177 try 178 { 179 JsonObject obj = StringToJsonObject(json); 180 object result = obj.ToHashList<HashT>(); 181 return result; 182 } 183 catch (Exception exp) 184 { 185 if (throwEeception) throw; 186 else 187 { 188 string logMsg = "JsonHelper.JsonDeserializeHasnList(string json) 反序列化错误:" + exp; 189 Tools.LogError(logMsg, "Logs/Tools/ErrorLog/"); 190 return null; 191 } 192 } 193 } 194 195 196 /// <summary> 197 /// 将 JsonObject 实体 分析成 指定的类型 198 /// </summary> 199 public static T JsonObjectToObject<T>(JsonObject obj) 200 { 201 if (obj == null) return default(T); 202 object result = JsonObjectToObject(obj, typeof (T)); 203 return (T)result; 204 } 205 /// <summary> 206 /// 将 JsonObject 实体 分析成 指定的类型 207 /// </summary> 208 public static object JsonObjectToObject(JsonObject obj, Type type) 209 { 210 if (obj == null) return null; 211 return obj.ToObject(type); 212 } 213 214 215 #endregion 216 217 218 #region 私 有 函 数 219 220 private static DateTime m_StampRoot = new DateTime(1970, 01, 01, 00, 00, 00, 00, DateTimeKind.Utc); 221 private static readonly Regex m_RegNum = new Regex(@"\d+", RegexOptions.Compiled | RegexOptions.IgnoreCase); 222 223 /// <summary> 224 /// Json时间戳 转 时间 225 /// </summary> 226 public static DateTime StampToDateTime(string timeStamp) 227 { 228 Match match = m_RegNum.Match(timeStamp); 229 if (!match.Success) return m_StampRoot; 230 long num = long.Parse(match.Value); 231 return StampToDateTime(num); 232 } 233 /// <summary> 234 /// Json时间戳 转 时间 235 /// </summary> 236 public static DateTime StampToDateTime(long timeStamp) 237 { 238 return m_StampRoot.AddMilliseconds(timeStamp).ToLocalTime(); 239 } 240 /// <summary> 241 /// 时间 转 Json时间戳 242 /// </summary> 243 public static long DateTimeToStamp(DateTime time) 244 { 245 return (long)(time.ToUniversalTime() - m_StampRoot).TotalMilliseconds; 246 } 247 248 private static bool IsNullOrWhiteSpace(string value) 249 { 250 if (value == null) return true; 251 for (int i = 0; i < value.Length; i++) 252 if (!char.IsWhiteSpace(value[i])) 253 return false; 254 return true; 255 } 256 257 #endregion 258 259 260 #region 核 心 算 法 261 262 263 private static JsonObject ObjectToJsonObject(object data) 264 { 265 if (data == null) return null; 266 267 Type type = data.GetType(); 268 269 if (ReflectHelper.IsMetaType(type)) 270 { 271 return new JsonValue(data, false); 272 } 273 else if (data is IDictionary) 274 { 275 JsonHash jsonHash = new JsonHash(); 276 IDictionary hash = (IDictionary) data; 277 foreach (object key in hash.Keys) 278 { 279 object value = hash[key]; 280 JsonObject jsonV = ObjectToJsonObject(value); 281 jsonHash[key.ToString()] = jsonV; 282 } 283 return jsonHash; 284 } 285 else if (data is IList) 286 { 287 JsonList jsonList = new JsonList(); 288 foreach (object item in (IList)data) 289 { 290 JsonObject jsonObj = ObjectToJsonObject(item); 291 if (jsonObj != null) jsonList.Add(jsonObj); 292 } 293 return jsonList; 294 } 295 else 296 { 297 Hashtable hash = new Hashtable(); 298 FieldInfo[] listField = type.GetFields(); 299 PropertyInfo[] listProp = type.GetProperties(); 300 foreach (FieldInfo field in listField) 301 { 302 object fieldObj = ReflectHelper.GetValue(data, field); 303 hash[field.Name] = fieldObj; 304 } 305 foreach (PropertyInfo prop in listProp) 306 { 307 object propObj = ReflectHelper.GetValue(data, prop); 308 hash[prop.Name] = propObj; 309 } 310 return ObjectToJsonObject(hash); 311 } 312 } 313 private static JsonObject StringToJsonObject(string json) 314 { 315 List<JsonObject> queue = new List<JsonObject>(); 316 using (JsonReader reader = new JsonReader(json)) 317 { 318 while (!reader.IsEnd) 319 { 320 string item = reader.Read(); 321 if (string.IsNullOrEmpty(item)) continue; 322 if (item.Length == 1) 323 { 324 char @char = item[0]; 325 if (@char == ARRAY_BEGIN) 326 { 327 queue.Add(new JsonList()); 328 } 329 else if (@char == OBJECT_BEGIN) 330 { 331 queue.Add(new JsonHash()); 332 } 333 else if (@char == ITEM_SPLIT) 334 { 335 MergeLastJsonKeyValue(queue); 336 } 337 else if (@char == KV_SPLIT) 338 { 339 MergeLastJsonKeyValue(queue); 340 queue.Add(new JsonKeyValue()); 341 } 342 else if (@char == ARRAY_END) 343 { 344 MergeLastJsonKeyValue(queue); 345 346 #region 搜索最近的一个数组开始 347 348 int index = queue.FindLastIndex(x => x.IsList); 349 JsonList array = (JsonList)queue[index]; 350 for (int i = index + 1, count = queue.Count; i < count; i++) array.Add(queue[i]); 351 queue.RemoveRange(index + 1, queue.Count - index - 1); 352 353 #endregion 354 } 355 else if (@char == OBJECT_END) 356 { 357 MergeLastJsonKeyValue(queue); 358 359 #region 搜索最近的一个对象开始 360 361 int index = queue.FindLastIndex(x => x.IsHash); 362 JsonHash hash = (JsonHash)queue[index]; 363 List<JsonObject> list = new List<JsonObject>(); 364 for (int i = index + 1, count = queue.Count; i < count; i++) list.Add(queue[i]); 365 List<JsonObject> listKV = list.FindAll(x => (x is JsonKeyValue)); 366 367 for (int i = 0, count = listKV.Count; i < count; i++) 368 { 369 JsonKeyValue keyValue = (JsonKeyValue)listKV[i]; 370 hash.Hash[keyValue.Key.Value.ToString()] = keyValue.Value; 371 } 372 queue.RemoveRange(index + 1, queue.Count - index - 1); 373 374 #endregion 375 } 376 } 377 else 378 { 379 queue.Add(new JsonValue(item, true)); 380 } 381 } 382 reader.Dispose(); 383 } 384 385 int queueCount = queue.Count; 386 if (queueCount == 1) return queue[0]; 387 if (queueCount >= 2) 388 { 389 JsonList jsonList = new JsonList(); 390 foreach (JsonObject item in queue) jsonList.Add(item); 391 return jsonList; 392 } 393 394 return null; 395 } 396 private static void MergeLastJsonKeyValue(List<JsonObject> queue) 397 { 398 if (queue == null || queue.Count <= 2) return; 399 int count = queue.Count; 400 401 if (queue[count - 2] is JsonKeyValue) 402 { 403 //标准情况 404 JsonObject key = queue[count - 3]; 405 if (!(key is JsonValue)) return; 406 JsonObject value = queue[count - 1]; 407 JsonKeyValue keyValue = (JsonKeyValue)queue[count - 2]; 408 keyValue.Key = (JsonValue)key; 409 keyValue.Value = value; 410 queue.RemoveAt(count - 1); 411 queue.RemoveAt(count - 3); 412 } 413 else if (queue[count - 1] is JsonKeyValue) 414 { 415 //有键无值 416 JsonObject key = queue[count - 2]; 417 if (!(key is JsonValue)) return; 418 JsonKeyValue keyValue = (JsonKeyValue)queue[count - 2]; 419 keyValue.Key = (JsonValue)key; 420 queue.RemoveAt(count - 2); 421 } 422 423 424 } 425 426 427 428 429 430 private const int ARRAY_BEGIN = '['; 431 private const int ARRAY_END = ']'; 432 private const int OBJECT_BEGIN = '{'; 433 private const int OBJECT_END = '}'; 434 private const int ITEM_SPLIT = ','; 435 private const int KV_SPLIT = ':'; 436 private const int STR_APOS = '\''; 437 private const int STR_QUOT = '"'; 438 private const int STR_ESCAPE = '\\'; 439 private const int CHAR_SPACE = (int)' '; 440 private const int CHAR_R = (int)'\r'; 441 private const int CHAR_N = (int)'\n'; 442 private const int CHAR_T = (int)'\t'; 443 private const int CHAR_A = (int)'\a'; 444 private const int CHAR_B = (int)'\b'; 445 private const int CHAR_F = (int)'\f'; 446 private const int CHAR_V = (int)'\v'; 447 private const int CHAR_0 = (int)'\0'; 448 449 private class JsonReader : IDisposable 450 { 451 public JsonReader(string json) 452 { 453 //Json = FormatString(json); 454 Json = json; 455 Length = Json == null ? 0 : Json.Length; 456 } 457 458 private string Json = string.Empty; 459 private int Position = 0; 460 private int Length = 0; 461 internal bool IsEnd = false; 462 463 /// <summary> 464 /// 读取一个JSON的完整节点 字符串, 返回值可能有 [ ] { } , : String 465 /// </summary> 466 /// <returns></returns> 467 public string Read() 468 { 469 if (Length <= 0 || Position >= Length) return string.Empty; 470 471 StringBuilder sb = new StringBuilder(); 472 bool isApos = false, isQuot = false; int len = 0; 473 while (Position <= Length) 474 { 475 int p = Position; 476 char @char = Json[p]; 477 int @charv = (int)@char; 478 Position++; IsEnd = Position >= Length; 479 480 if (char.IsWhiteSpace(@char)) 481 { 482 if (/*sb.Length <= 0*/len <= 0) { continue; } 483 if (@charv != CHAR_SPACE && @charv != CHAR_R && @charv != CHAR_N && @charv != CHAR_T) { continue; } //转义符 仅保留 空格 \r \n \t 484 } 485 486 sb.Append(@char); len++; 487 488 int @pcharv = (int)((p - 1 >= 0) ? Json[p - 1] : char.MinValue); 489 if (!isApos && !isQuot) { if (@charv == STR_APOS && @pcharv != STR_ESCAPE) { isApos = true; } else if (@charv == STR_QUOT && @pcharv != STR_ESCAPE) { isQuot = true; } } 490 else if ((isApos || isQuot) && /*sb.Length > 1*/ len > 1) 491 { 492 if (isApos && @charv == STR_APOS && @pcharv != STR_ESCAPE) { isApos = false; } 493 else if (isQuot && @charv == STR_QUOT && @pcharv != STR_ESCAPE) { isQuot = false; } 494 } 495 496 if (!isApos && !isQuot) 497 { 498 if (IsConstChar(@charv)) break; 499 if (p + 1 < Length) { char @nchar = Json[p + 1]; if (IsConstChar((int)@nchar)) break; } 500 } 501 } 502 503 return sb.ToString().Trim(); 504 } 505 506 private static bool IsConstChar(int @charv) 507 { 508 return (@charv == ARRAY_BEGIN || @charv == ARRAY_END || @charv == OBJECT_BEGIN || @charv == OBJECT_END || @charv == ITEM_SPLIT || @charv == KV_SPLIT); 509 } 510 public void Dispose() 511 { 512 Json = null; 513 Position = Length = 0; 514 } 515 } 516 517 #endregion 518 519 520 521 522 523 524 525 526 } 527 528 529 #region Json 实 体 530 531 public abstract class JsonObject 532 { 533 public bool IsValue { get { return this is JsonValue; } } 534 public bool IsList { get { return this is JsonList; } } 535 public bool IsHash { get { return this is JsonHash; } } 536 public bool IsKeyValue { get { return this is JsonKeyValue; } } 537 538 public virtual string ToJson() 539 { 540 return ToJson(0, false); 541 } 542 public virtual string ToJson(int level) 543 { 544 return ToJson(level, false); 545 } 546 public abstract string ToJson(int level, bool format); 547 548 549 public abstract object ToObject(Type type); 550 public object ToHashList() 551 { 552 return InnerToHashList<Dictionary<string, object>>(); 553 } 554 public object ToHashList<HashT>() where HashT : IDictionary, new() 555 { 556 return InnerToHashList<HashT>(); 557 } 558 protected abstract object InnerToHashList<HashT>() where HashT : IDictionary, new(); 559 560 public override string ToString() 561 { 562 return ToJson(0, true); 563 } 564 } 565 public class JsonValue : JsonObject 566 { 567 public JsonValue() { } 568 public JsonValue(object value) : this(value, false) 569 { 570 } 571 public JsonValue(object value, bool json) 572 { 573 this.m_Value = FmtValue(value, json); 574 } 575 576 private object m_Value = null; 577 578 public string Json 579 { 580 get 581 { 582 object value = m_Value; 583 //理论上这两行代码 不可达, 理论上 m_Value 不可能是 Json对象 584 if (value is JsonValue) return ((JsonValue)value).Json; 585 if (value is JsonObject) return ((JsonObject)value).ToJson(); 586 587 if (m_Value == null) return "null"; 588 if (m_Value is bool) return ((bool)m_Value).ToString().ToLower(); 589 if (m_Value is Guid) return "\"" + ((Guid)m_Value).ToString("D") + "\""; 590 if (m_Value is DateTime) return "\"" + ((DateTime)m_Value).ToString("yyyy-MM-ddTHH:mm:ss.fffffff") + "\""; 591 if (m_Value is StringBuilder || m_Value is string || m_Value is char) return "\"" + StringToJsonString(m_Value.ToString()) + "\""; 592 if (m_Value is byte || m_Value is short || m_Value is int || m_Value is long || m_Value is sbyte || m_Value is ushort || m_Value is uint || m_Value is ulong) return m_Value.ToString(); 593 if (m_Value is float || m_Value is double || m_Value is decimal) return m_Value.ToString(); 594 595 //if (m_Value is float) return ((float)m_Value).ToString(); 596 //if (m_Value is double) return ((double)m_Value).ToString(); 597 //if (m_Value is decimal) return ((decimal)m_Value).ToString(); 598 599 return "\"" + StringToJsonString(m_Value.ToString()) + "\""; 600 } 601 } 602 public object Value 603 { 604 get { return m_Value; } 605 set { this.m_Value = FmtValue(value, false); } 606 } 607 608 private static object FmtValue(object value, bool json) 609 { 610 if (value == null) { return null; } 611 if (value is bool) { return (bool)value; } 612 if (value is Guid) { return (Guid)value; } 613 if (value is DateTime) { return (DateTime)value; } 614 if (value is StringBuilder || value is string || value is char) 615 { 616 string temp = value.ToString(); 617 int len = temp.Length; 618 if (json && len >= 2 && temp[0] == '"' && temp[len - 1] == '"') 619 { 620 string str = JsonStringToString(temp.Substring(1, len - 2)); 621 DateTime time; if (TryToDateTime(str, out time)) return time; 622 return str; 623 } 624 else if (json && len >= 2 && temp[0] == '\'' && temp[len - 1] == '\'') 625 { 626 string str = JsonStringToString(temp.Substring(1, len - 2)); 627 DateTime time; if (TryToDateTime(str, out time)) return time; 628 return str; 629 } 630 else 631 { 632 if (json) 633 { 634 //bool float 不需要引号 635 string trim = temp.Trim(); 636 string lower = trim.ToLower(); 637 if (lower == "null") return null; 638 if (lower == "true") return true; 639 if (lower == "false") return false; 640 if (lower.StartsWith("new ")) return trim; 641 DateTime time; if (TryToDateTime(lower, out time)) return time; 642 double doub; if (double.TryParse(trim, out doub)) return doub; 643 } 644 645 return temp; 646 } 647 } 648 return value; 649 } 650 private static bool TryToDateTime(string source, out DateTime time) 651 { 652 try 653 { 654 string lower = source.ToLower(); 655 if (lower.StartsWith("/date(") || lower.StartsWith("date(") || lower.StartsWith("\\/date(")) 656 { 657 //兼容微软最初的 Json时间格式 "Birthday":"\/Date(734840435887)\/" 658 time = JsonHelper.StampToDateTime(lower); 659 return (time != DateTime.MinValue); 660 } 661 } 662 catch (Exception) { } 663 time = DateTime.MinValue; 664 return false; 665 } 666 667 668 669 670 671 public override object ToObject(Type type) 672 { 673 if (type == null || type == typeof (object)) return Value; 674 return ReflectHelper.ChangeType(Value, type); 675 } 676 public override string ToJson(int level, bool format) 677 { 678 //return new string(' ', level*2) + Value; 679 return Json; 680 } 681 protected override object InnerToHashList<HashT>() 682 { 683 if (Value == null) return null; 684 if (Value is JsonObject) return ((JsonObject)Value).ToHashList<HashT>(); 685 return Value; 686 } 687 688 689 private static string JsonStringToString(string json) 690 { 691 if (string.IsNullOrEmpty(json)) return string.Empty; 692 StringBuilder sb = new StringBuilder(); 693 for (int i = 0, c = json.Length; i < c; i++) 694 { 695 char @char = json[i]; 696 if (@char != '\\') { sb.Append(@char); continue; } 697 if (i + 1 >= c) { sb.Append(@char); continue; } 698 char @charn = json[i + 1]; 699 if (@charn == '\\') { sb.Append('\\'); i++; continue; } 700 if (@charn == 'r') { sb.Append('\r'); i++; continue; } 701 if (@charn == 'n') { sb.Append('\n'); i++; continue; } 702 if (@charn == 't') { sb.Append('\t'); i++; continue; } 703 if (@charn == 'a') { sb.Append('\a'); i++; continue; } 704 if (@charn == 'b') { sb.Append('\b'); i++; continue; } 705 if (@charn == 'f') { sb.Append('\f'); i++; continue; } 706 if (@charn == 'v') { sb.Append('\v'); i++; continue; } 707 if (@charn == '"') { sb.Append('"'); i++; continue; } 708 if (@charn == '\'') { sb.Append('\''); i++; continue; } 709 if (@charn == '0') { /*sb.Append('\0');*/ i++; continue; } // \0字符直接排除 710 711 if (@charn == 'u') 712 { 713 //\uFFFF 一是 Unicode 字符, 这类字符 一般是 4位 \uFFFF, 但是理论上 可以有5位 \uFFFFF 714 string hex = json.Substring(i + 2, 4); 715 //char h5 = json[i + 2 + 4]; 716 //bool isHex5 = (h5 == '0' || h5 == '1' || h5 == '2' || h5 == '3' || h5 == '4' || h5 == '5' || h5 == '6' || h5 == '7' || h5 == '8' || h5 == '9' || h5 == 'a' || h5 == 'b' || h5 == 'c' || h5 == 'd' || h5 == 'e' || h5 == 'f' || h5 == 'A' || h5 == 'B' || h5 == 'C' || h5 == 'D' || h5 == 'E' || h5 == 'F'); 717 //if (isHex5) hex = hex + h5; 718 int num; 719 if (int.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out num)) 720 { 721 sb.Append((char)num); i = i + 5; /*if (isHex5){i++;} */continue; 722 } 723 else { sb.Append("\\u"); i++; continue; } 724 } 725 } 726 return sb.ToString(); 727 } 728 internal static string StringToJsonString(string str) 729 { 730 if (string.IsNullOrEmpty(str)) return string.Empty; 731 732 StringBuilder sb = new StringBuilder(); 733 for (int i = 0, c = str.Length; i < c; i++) 734 { 735 char @char = str[i]; 736 //if (@char == '\'') { sb.Append("\\'"); continue; } //单引号不再进行转义 737 if (@char == '"') { sb.Append("\\\""); continue; } 738 if (@char == '\\') { sb.Append("\\\\"); continue; } 739 if (@char == '\r') { sb.Append("\\r"); continue; } 740 if (@char == '\n') { sb.Append("\\n"); continue; } 741 if (@char == '\t') { sb.Append("\\t"); continue; } 742 if (@char == '\a') { sb.Append("\\a"); continue; } 743 if (@char == '\b') { sb.Append("\\b"); continue; } 744 if (@char == '\f') { sb.Append("\\f"); continue; } 745 if (@char == '\v') { sb.Append("\\v"); continue; } 746 if (@char == '\0') { /*sb.Append('\\\0');*/ continue; } // \0字符直接排除 747 sb.Append(@char); 748 } 749 return sb.ToString(); 750 } 751 } 752 public class JsonKeyValue : JsonObject 753 { 754 public JsonKeyValue() { } 755 public JsonKeyValue(JsonValue key, JsonObject value) { this.Key = key; this.Value = value; } 756 757 public JsonValue Key { get; set; } 758 public JsonObject Value { get; set; } 759 760 public override object ToObject(Type type) 761 { 762 object obj = Activator.CreateInstance(type); 763 764 ReflectHelper.SetValue(obj, "Key", (Key == null ? string.Empty : Key.Value.ToString())); 765 766 Type propOrFieldType = ReflectHelper.GetPropertyOrFieldType(type, "Value"); 767 object value = (Value == null ? null : Value.ToObject(propOrFieldType)); 768 ReflectHelper.SetValue(obj, "Value", value); 769 770 return obj; 771 } 772 public override string ToJson(int level, bool format) 773 { 774 return string.Format((format ? @"{0}: {1}" : @"{0}:{1}"), (Key == null ? string.Empty : Key.ToJson(0, false)), (Value == null ? "null" : Value.ToJson(level, format))); 775 } 776 public new KeyValuePair<string, object> ToHashList() 777 { 778 return (KeyValuePair<string, object>)InnerToHashList<Dictionary<string, object>>(); 779 } 780 public new KeyValuePair<string, object> ToHashList<HashT>() where HashT : IDictionary, new() 781 { 782 return (KeyValuePair<string, object>)InnerToHashList<HashT>(); 783 } 784 protected override object InnerToHashList<HashT>() 785 { 786 return new KeyValuePair<string, object>((Key == null ? string.Empty : Key.Value.ToString()), (Value == null ? null : Value.ToHashList<HashT>())); 787 } 788 } 789 public class JsonList : JsonObject, IList, IList<JsonObject> 790 { 791 public bool HasValues { get; set; } 792 793 [NonSerialized] 794 private List<JsonObject> m_List; 795 private List<JsonObject> List 796 { 797 get { return m_List ?? (m_List = new List<JsonObject>()); } 798 } 799 800 801 public int Count 802 { 803 get { return this.List.Count; } 804 } 805 public JsonObject this[int index] 806 { 807 get { return this.List[index]; } 808 set { this.List[index] = value; } 809 } 810 public void Add(JsonObject item) 811 { 812 this.List.Add(item); 813 } 814 public void Insert(int index, JsonObject item) 815 { 816 this.List.Insert(index, item); 817 } 818 public void Remove(JsonObject item) 819 { 820 this.List.Remove(item); 821 } 822 public void RemoveAt(int index) 823 { 824 this.List.RemoveAt(index); 825 } 826 public void Clear() 827 { 828 this.List.Clear(); 829 } 830 public bool Contains(JsonObject item) 831 { 832 return this.List.Contains(item); 833 } 834 public int IndexOf(JsonObject item) 835 { 836 return this.List.IndexOf(item); 837 } 838 public void CopyTo(JsonObject[] array, int arrayIndex) 839 { 840 this.List.CopyTo(array, arrayIndex); 841 } 842 843 844 845 public override object ToObject(Type type) 846 { 847 if (m_List == null) return null; 848 849 Type listType = null; 850 Type itemType = null; 851 int sign = 0; 852 if (type.IsArray) { listType = type; itemType = listType.GetElementType(); sign = 3; } 853 else if (typeof(IList<>).IsAssignableFrom(type)) { listType = type; itemType = GetListElementType(listType); sign = 2; } 854 else if (typeof(IList).IsAssignableFrom(type)) { listType = type; itemType = typeof(object); sign = 1; } 855 else { listType = typeof(List<>).MakeGenericType(type); itemType = type; sign = 0; } 856 857 if (sign < 0 || listType == null || ((sign == 2 || sign == 3) && listType.IsGenericTypeDefinition)) 858 throw new Exception(string.Format("JsonList 无法反序列化得到类型: {0}", type.FullName)); 859 860 int count = (m_List != null) ? m_List.Count : 0; 861 if (sign == 0 || sign == 1 || sign == 2) 862 { 863 IList list = (IList)Activator.CreateInstance(listType); 864 if (count >= 1) 865 foreach (JsonObject item in m_List) 866 { 867 object obj = item.ToObject(itemType); 868 list.Add(obj); 869 } 870 return list; 871 } 872 else if (sign == 3) 873 { 874 Array array = Array.CreateInstance(itemType, count); 875 if (count >= 1) 876 for (int i = 0; i < count; i++) 877 { 878 JsonObject item = m_List[i]; 879 object obj = item.ToObject(itemType); 880 array.SetValue(obj, i); 881 } 882 return array; 883 } 884 885 return null; 886 } 887 public override string ToJson(int level, bool format) 888 { 889 string rn = !format ? string.Empty : "\r\n"; 890 string prev = !format ? string.Empty : new string(' ', (level) * 2); 891 string prev2 = !format ? string.Empty : new string(' ', (level + 1) * 2); 892 StringBuilder sb = new StringBuilder(); 893 sb.Append("[" + rn); 894 if (m_List != null) 895 { 896 List<string> list = new List<string>(); 897 foreach (JsonObject item in m_List) 898 list.Add(prev2 + item.ToJson(level + 1, format)); 899 900 for (int i = 0, count = list.Count; i < count; i++) 901 sb.Append(list[i] + (i == count - 1 ? string.Empty : ",") + rn); 902 } 903 sb.Append(prev + "]"); 904 return sb.ToString(); 905 } 906 public new List<object> ToHashList() 907 { 908 return (List<object>)InnerToHashList<Dictionary<string, object>>(); 909 } 910 public new List<object> ToHashList<HashT>() where HashT : IDictionary, new() 911 { 912 return (List<object>)InnerToHashList<HashT>(); 913 } 914 protected override object InnerToHashList<HashT>() 915 { 916 if (m_List == null) return null; 917 918 List<object> list = new List<object>(); 919 foreach (JsonObject item in m_List) 920 list.Add(item.ToHashList<HashT>()); 921 return list; 922 } 923 924 925 /// <summary> 926 /// 查找指定 List类型, 对应的 集合成员类型 927 /// </summary> 928 public static Type GetListElementType(Type listType) 929 { 930 Type baseType = listType; 931 Type[] itfsTypes = baseType.GetInterfaces(); 932 foreach (Type itfsType in itfsTypes) 933 { 934 if (itfsType.IsGenericType && !itfsType.IsGenericTypeDefinition && typeof(IList<>) == itfsType.GetGenericTypeDefinition()) 935 { 936 Type[] genericTypes = itfsType.GetGenericArguments(); 937 if (genericTypes.Length == 1) return genericTypes[0]; 938 } 939 } 940 941 foreach (Type itfsType in itfsTypes) 942 { 943 if (itfsType.IsGenericType && !itfsType.IsGenericTypeDefinition && typeof(ICollection<>) == itfsType.GetGenericTypeDefinition()) 944 { 945 Type[] genericTypes = itfsType.GetGenericArguments(); 946 if (genericTypes.Length == 1) return genericTypes[0]; 947 } 948 } 949 950 if (typeof(IList).IsAssignableFrom(listType)) { return typeof(object); } 951 return null; 952 } 953 954 955 #region 中转的继承 956 957 IEnumerator<JsonObject> IEnumerable<JsonObject>.GetEnumerator() 958 { 959 return ((IEnumerable<JsonObject>)this.List).GetEnumerator(); 960 } 961 IEnumerator IEnumerable.GetEnumerator() 962 { 963 return ((IEnumerable)this.List).GetEnumerator(); 964 } 965 void ICollection.CopyTo(Array array, int index) 966 { 967 ((ICollection)this.List).CopyTo(array, index); 968 } 969 bool ICollection<JsonObject>.Remove(JsonObject item) 970 { 971 return ((ICollection<JsonObject>)this.List).Remove(item); 972 } 973 int ICollection<JsonObject>.Count 974 { 975 get { return ((ICollection<JsonObject>)this.List).Count; } 976 } 977 bool ICollection<JsonObject>.IsReadOnly 978 { 979 get { return ((ICollection<JsonObject>)this.List).IsReadOnly; } 980 } 981 int ICollection.Count 982 { 983 get { return ((ICollection)this.List).Count; } 984 } 985 object ICollection.SyncRoot 986 { 987 get { return ((ICollection)this.List).SyncRoot; } 988 } 989 bool ICollection.IsSynchronized 990 { 991 get { return ((ICollection)this.List).IsSynchronized; } 992 } 993 int IList.Add(object value) 994 { 995 return ((IList)this.List).Add(value); 996 } 997 bool IList.Contains(object value) 998 { 999 return ((IList)this.List).Contains(value); 1000 } 1001 void ICollection<JsonObject>.Add(JsonObject item) 1002 { 1003 ((ICollection<JsonObject>)this.List).Add(item); 1004 } 1005 void ICollection<JsonObject>.Clear() 1006 { 1007 ((ICollection<JsonObject>)this.List).Clear(); 1008 } 1009 bool ICollection<JsonObject>.Contains(JsonObject item) 1010 { 1011 return ((ICollection<JsonObject>)this.List).Contains(item); 1012 } 1013 void ICollection<JsonObject>.CopyTo(JsonObject[] array, int arrayIndex) 1014 { 1015 ((ICollection<JsonObject>)this.List).CopyTo(array, arrayIndex); 1016 } 1017 void IList.Clear() 1018 { 1019 ((IList)this.List).Clear(); 1020 } 1021 int IList.IndexOf(object value) 1022 { 1023 return ((IList)this.List).IndexOf(value); 1024 } 1025 void IList.Insert(int index, object value) 1026 { 1027 ((IList)this.List).Insert(index, value); 1028 } 1029 void IList.Remove(object value) 1030 { 1031 ((IList)this.List).Remove(value); 1032 } 1033 int IList<JsonObject>.IndexOf(JsonObject item) 1034 { 1035 return ((IList<JsonObject>)this.List).IndexOf(item); 1036 } 1037 void IList<JsonObject>.Insert(int index, JsonObject item) 1038 { 1039 ((IList<JsonObject>)this.List).Insert(index, item); 1040 } 1041 void IList<JsonObject>.RemoveAt(int index) 1042 { 1043 ((IList<JsonObject>)this.List).RemoveAt(index); 1044 } 1045 JsonObject IList<JsonObject>.this[int index] 1046 { 1047 get { return ((IList<JsonObject>)this.List)[index]; } 1048 set { ((IList<JsonObject>)this.List)[index] = value; } 1049 } 1050 void IList.RemoveAt(int index) 1051 { 1052 ((IList)this.List).RemoveAt(index); 1053 } 1054 object IList.this[int index] 1055 { 1056 get { return ((IList)this.List)[index]; } 1057 set { ((IList)this.List)[index]=value; } 1058 } 1059 bool IList.IsReadOnly 1060 { 1061 get { return ((IList)this.List).IsReadOnly; } 1062 } 1063 bool IList.IsFixedSize 1064 { 1065 get { return ((IList)this.List).IsFixedSize; } 1066 } 1067 1068 #endregion 1069 } 1070 public class JsonHash : JsonObject, IDictionary, IDictionary<string, JsonObject> 1071 { 1072 public bool HasValues { get; set; } 1073 1074 [NonSerialized] 1075 private Dictionary<string, JsonObject> m_Hash; 1076 public Dictionary<string, JsonObject> Hash 1077 { 1078 get { return m_Hash ?? (m_Hash = new Dictionary<string, JsonObject>()); } 1079 } 1080 1081 1082 public JsonObject this[string key] 1083 { 1084 get 1085 { 1086 if (m_Hash == null || m_Hash.Count <= 0) return null; 1087 JsonObject value; 1088 if (m_Hash.TryGetValue(key, out value)) return value; 1089 return null; 1090 } 1091 set 1092 { 1093 if (key == null) return; 1094 if (!this.Hash.ContainsKey(key)) this.Hash.Add(key, value); 1095 else this.Hash[key] = value; 1096 } 1097 } 1098 public int Count 1099 { 1100 get { return this.Hash.Count; } 1101 } 1102 public void Add(string key, JsonObject value) 1103 { 1104 this.Hash.Add(key, value); 1105 } 1106 public void Remove(string key) 1107 { 1108 this.Hash.Remove(key); 1109 } 1110 public void Clear() 1111 { 1112 this.Hash.Clear(); 1113 } 1114 public bool ContainsKey(string key) 1115 { 1116 return this.Hash.ContainsKey(key); 1117 } 1118 public bool TryGetValue(string key, out JsonObject value) 1119 { 1120 return this.Hash.TryGetValue(key, out value); 1121 } 1122 public ICollection<string> Keys 1123 { 1124 get { return this.Hash.Keys; } 1125 } 1126 public ICollection<JsonObject> Values 1127 { 1128 get { return this.Hash.Values; } 1129 } 1130 1131 1132 1133 public override object ToObject(Type type) 1134 { 1135 if (m_Hash == null) return null; 1136 1137 int sign = 0; 1138 if (type == null || type == typeof(object) || typeof(IDictionary).IsAssignableFrom(type)) { if (type == null || type == typeof(object)) { type = typeof(Hashtable); } sign = 1; } 1139 else { sign = 0; } 1140 1141 if (sign < 0 || (sign == 1 && type.IsGenericTypeDefinition)) 1142 throw new Exception(string.Format("JsonHash 无法反序列化得到类型: {0}", type.FullName)); 1143 1144 int count = (m_Hash != null) ? m_Hash.Count : 0; 1145 if (sign == 1) 1146 { 1147 IDictionary hash = (IDictionary)Activator.CreateInstance(type); 1148 if (count >= 1) 1149 foreach (KeyValuePair<string, JsonObject> pair in m_Hash) 1150 { 1151 object obj = pair.Value.ToObject(typeof(object)); 1152 if (hash.Contains(pair.Key)) hash[pair.Key] = obj; 1153 else hash.Add(pair.Key, obj); 1154 } 1155 return hash; 1156 } 1157 else if (sign == 0) 1158 { 1159 object hash = Activator.CreateInstance(type); 1160 if (count >= 1) 1161 foreach (KeyValuePair<string, JsonObject> pair in m_Hash) 1162 { 1163 string key = pair.Key; 1164 Type propOrFieldType = ReflectHelper.GetPropertyOrFieldType(type, key); 1165 object value = (pair.Value == null ? null : pair.Value.ToObject(propOrFieldType)); 1166 ReflectHelper.SetValue(hash, key, value); 1167 } 1168 return hash; 1169 } 1170 1171 return null; 1172 } 1173 1174 public override string ToJson(int level, bool format) 1175 { 1176 string rn = !format ? string.Empty : "\r\n"; 1177 string prev = !format ? string.Empty : new string(' ', (level) * 2); 1178 string prev2 = !format ? string.Empty : new string(' ', (level + 1) * 2); 1179 StringBuilder sb = new StringBuilder(); 1180 sb.Append("{" + rn); 1181 if (m_Hash != null) 1182 { 1183 List<string> list = new List<string>(); 1184 foreach (KeyValuePair<string, JsonObject> pair in m_Hash) 1185 list.Add(prev2 + string.Format((format ? @"""{0}"": {1}" : @"""{0}"":{1}"), (pair.Key ?? string.Empty), (pair.Value == null ? "null" : pair.Value.ToJson(level + 1, format)))); 1186 1187 for (int i = 0, count = list.Count; i < count; i++) 1188 sb.Append(list[i] + (i == count - 1 ? string.Empty : ",") + rn); 1189 } 1190 sb.Append(prev + "}"); 1191 return sb.ToString(); 1192 } 1193 public new Dictionary<string, object> ToHashList() 1194 { 1195 return (Dictionary<string, object>)InnerToHashList<Dictionary<string, object>>(); 1196 } 1197 public new HashT ToHashList<HashT>() where HashT : IDictionary, new() 1198 { 1199 return (HashT)InnerToHashList<HashT>(); 1200 } 1201 protected override object InnerToHashList<HashT>() 1202 { 1203 if (m_Hash == null) return null; 1204 1205 HashT hash = new HashT(); 1206 foreach (KeyValuePair<string, JsonObject> pair in m_Hash) 1207 { 1208 if (hash.Contains(pair.Key)) hash[pair.Key] = pair.Value.ToHashList<HashT>(); 1209 else hash.Add(pair.Key, pair.Value.ToHashList<HashT>()); 1210 } 1211 return hash; 1212 } 1213 1214 1215 #region 中转的继承 1216 1217 bool IDictionary.Contains(object key) 1218 { 1219 return ((IDictionary)this.Hash).Contains(key); 1220 } 1221 void IDictionary.Add(object key, object value) 1222 { 1223 ((IDictionary)this.Hash).Add(key, value); 1224 } 1225 void ICollection<KeyValuePair<string, JsonObject>>.Add(KeyValuePair<string, JsonObject> item) 1226 { 1227 ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).Add(item); 1228 } 1229 void ICollection<KeyValuePair<string, JsonObject>>.Clear() 1230 { 1231 ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).Clear(); 1232 } 1233 bool ICollection<KeyValuePair<string, JsonObject>>.Contains(KeyValuePair<string, JsonObject> item) 1234 { 1235 return ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).Contains(item); 1236 } 1237 void ICollection<KeyValuePair<string, JsonObject>>.CopyTo(KeyValuePair<string, JsonObject>[] array, int arrayIndex) 1238 { 1239 ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).CopyTo(array, arrayIndex); 1240 } 1241 bool ICollection<KeyValuePair<string, JsonObject>>.Remove(KeyValuePair<string, JsonObject> item) 1242 { 1243 return ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).Remove(item); 1244 } 1245 int ICollection<KeyValuePair<string, JsonObject>>.Count 1246 { 1247 get { return ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).Count; } 1248 } 1249 bool ICollection<KeyValuePair<string, JsonObject>>.IsReadOnly 1250 { 1251 get { return ((ICollection<KeyValuePair<string, JsonObject>>)this.Hash).IsReadOnly; } 1252 } 1253 void IDictionary.Clear() 1254 { 1255 ((IDictionary)this.Hash).Clear(); 1256 } 1257 IEnumerator<KeyValuePair<string, JsonObject>> IEnumerable<KeyValuePair<string, JsonObject>>.GetEnumerator() 1258 { 1259 return ((IEnumerable<KeyValuePair<string, JsonObject>>)this.Hash).GetEnumerator(); 1260 } 1261 IDictionaryEnumerator IDictionary.GetEnumerator() 1262 { 1263 return ((IDictionary)this.Hash).GetEnumerator(); 1264 } 1265 void IDictionary.Remove(object key) 1266 { 1267 ((IDictionary)this.Hash).Remove(key); 1268 } 1269 object IDictionary.this[object key] 1270 { 1271 get { return ((IDictionary)this.Hash)[key]; } 1272 set { ((IDictionary)this.Hash)[key] = value; } 1273 } 1274 bool IDictionary<string, JsonObject>.ContainsKey(string key) 1275 { 1276 return ((IDictionary<string, JsonObject>)this.Hash).ContainsKey(key); 1277 } 1278 void IDictionary<string, JsonObject>.Add(string key, JsonObject value) 1279 { 1280 ((IDictionary<string, JsonObject>)this.Hash).Add(key, value); 1281 } 1282 bool IDictionary<string, JsonObject>.Remove(string key) 1283 { 1284 return ((IDictionary<string, JsonObject>)this.Hash).Remove(key); 1285 } 1286 bool IDictionary<string, JsonObject>.TryGetValue(string key, out JsonObject value) 1287 { 1288 return ((IDictionary<string, JsonObject>)this.Hash).TryGetValue(key, out value); 1289 } 1290 JsonObject IDictionary<string, JsonObject>.this[string key] 1291 { 1292 get { return ((IDictionary<string, JsonObject>)this.Hash)[key]; } 1293 set { ((IDictionary<string, JsonObject>)this.Hash)[key] = value; } 1294 } 1295 ICollection IDictionary.Keys 1296 { 1297 get { return ((IDictionary)this.Hash).Keys; } 1298 } 1299 ICollection<JsonObject> IDictionary<string, JsonObject>.Values 1300 { 1301 get { return ((IDictionary<string, JsonObject>)this.Hash).Values; } 1302 } 1303 ICollection<string> IDictionary<string, JsonObject>.Keys 1304 { 1305 get { return ((IDictionary<string, JsonObject>)this.Hash).Keys; } 1306 } 1307 ICollection IDictionary.Values 1308 { 1309 get { return ((IDictionary)this.Hash).Values; } 1310 } 1311 bool IDictionary.IsReadOnly 1312 { 1313 get { return ((IDictionary)this.Hash).IsReadOnly; } 1314 } 1315 bool IDictionary.IsFixedSize 1316 { 1317 get { return ((IDictionary)this.Hash).IsFixedSize; } 1318 } 1319 IEnumerator IEnumerable.GetEnumerator() 1320 { 1321 return ((IEnumerable)this.Hash).GetEnumerator(); 1322 } 1323 void ICollection.CopyTo(Array array, int index) 1324 { 1325 ((ICollection)this.Hash).CopyTo(array, index); 1326 } 1327 int ICollection.Count 1328 { 1329 get { return ((ICollection)this.Hash).Count; } 1330 } 1331 object ICollection.SyncRoot 1332 { 1333 get { return ((ICollection)this.Hash).SyncRoot; } 1334 } 1335 bool ICollection.IsSynchronized 1336 { 1337 get { return ((ICollection)this.Hash).IsSynchronized; } 1338 } 1339 1340 #endregion 1341 } 1342 1343 #endregion 1344 }
JsonHelper_Test 源码:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.IO; 5 using System.Linq; 6 using System.Text; 7 using System.Web.Script.Serialization; 8 using InkFx.Utils.Test.Properties; 9 using NUnit.Framework; 10 11 namespace InkFx.Utils.Test 12 { 13 public class Test_JsonHelper 14 { 15 [Test] 16 public void TestDeserialize() 17 { 18 string json = Resources.TestObjectJson2.Trim(); 19 20 JsonObject jsonObj = JsonHelper.JsonDeserializeObject(json); 21 DateTime beginTime = DateTime.Now; 22 for (int i = 0; i < 100000; i++) 23 { 24 jsonObj = JsonHelper.JsonDeserializeObject(json); 25 } 26 DateTime endTime = DateTime.Now; 27 Console.WriteLine(@"耗时: " + (endTime - beginTime).TotalMilliseconds); 28 Console.WriteLine(jsonObj); 29 Console.WriteLine(jsonObj.ToJson()); 30 Console.WriteLine(jsonObj.ToHashList()); 31 } 32 [Test] 33 public void TestDeserialize2() 34 { 35 string json = Resources.TestObjectJson2.Trim(); 36 37 DateTime beginTime = DateTime.Now; 38 object jsonObj = null; 39 for (int i = 0; i < 100000; i++) 40 { 41 jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json); 42 } 43 DateTime endTime = DateTime.Now; 44 Console.WriteLine(@"耗时: " + (endTime - beginTime).TotalMilliseconds); 45 Console.WriteLine(jsonObj); 46 } 47 48 49 [Test] 50 public void TestSerializeMetaValue() 51 { 52 Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(DateTime.Now)); 53 Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject("AAACCC\"VVV\" CF[] {}, \'\' FCVD")); 54 Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(15)); 55 Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(false)); 56 Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(null)); 57 58 Console.WriteLine(JsonHelper.JsonSerialize(DateTime.Now)); 59 Console.WriteLine(JsonHelper.JsonSerialize("AAACCC\"VVV\" CF[] {}, \'\' FCVD")); 60 Console.WriteLine(JsonHelper.JsonSerialize(15)); 61 Console.WriteLine(JsonHelper.JsonSerialize(false)); 62 Console.WriteLine(JsonHelper.JsonSerialize(null)); 63 } 64 [Test] 65 public void TestDeserializeMetaValue() 66 { 67 Console.WriteLine(Newtonsoft.Json.JsonConvert.DeserializeObject<DateTime>("\"2017-11-24T22:54:01.7724502+08:00\"")); //反序列化失败 68 Console.WriteLine(Newtonsoft.Json.JsonConvert.DeserializeObject<string>("\"AAACCC\\\"VVV\\\" CF[] {}, \'\' FCVD\"")); 69 Console.WriteLine(Newtonsoft.Json.JsonConvert.DeserializeObject<int>("15")); 70 Console.WriteLine(Newtonsoft.Json.JsonConvert.DeserializeObject<bool>("false")); 71 //Console.WriteLine(Newtonsoft.Json.JsonConvert.DeserializeObject<object>(null)); 72 73 Console.WriteLine(JsonHelper.JsonDeserialize<DateTime>("\"2017-11-24T22:54:01.7724502+08:00\"")); 74 Console.WriteLine(JsonHelper.JsonDeserialize<string>("AAACCC\"VVV\" CF[] {}, \'\' FCVD")); 75 Console.WriteLine(JsonHelper.JsonDeserialize<int>("15")); 76 Console.WriteLine(JsonHelper.JsonDeserialize<bool>("false")); 77 Console.WriteLine(JsonHelper.JsonDeserialize<object>(null)); 78 } 79 80 81 [Test] 82 public void TestDeserializeObject() 83 { 84 TestClass item = new TestClass(); 85 item.Name = "\\张三'\"'''AAB\r\nBCC\"\"\""; 86 item.Age = 24; 87 item.Birthday = new DateTime(1993, 04, 15, 10, 20, 35, 887); 88 item.Money = 123456789012345678901234567890123456789f; 89 item.Info = new TestClass {Name = "李四", Age = 22, Birthday = new DateTime(1995, 05, 20), Money = 1234}; 90 91 string webJson = SystemWebJson(item); 92 Console.WriteLine(webJson); 93 Console.WriteLine(); 94 95 string json = Newtonsoft.Json.JsonConvert.SerializeObject(item); 96 Console.WriteLine(json); 97 Console.WriteLine(); 98 99 JsonObject obj = null; 100 object reObj = null; 101 DateTime beginTime = DateTime.Now; 102 for (int i = 0; i < 100000; i++) 103 { 104 obj = JsonHelper.JsonDeserializeObject(webJson); 105 reObj = obj.ToObject(typeof(TestClass)); 106 } 107 DateTime endTime = DateTime.Now; 108 Console.WriteLine(@"耗时: " + (endTime - beginTime).TotalMilliseconds); 109 Console.WriteLine(obj.ToJson()); 110 Console.WriteLine(obj.ToString()); 111 Console.WriteLine(reObj); 112 } 113 [Test] 114 public void TestDeserializeObject2() 115 { 116 TestClass item = new TestClass(); 117 item.Name = "\\张三'\"'''AAB\r\nBCC\"\"\""; 118 item.Age = 24; 119 item.Birthday = new DateTime(1993, 04, 15, 10, 20, 35, 887); 120 item.Money = 123456789012345678901234567890123456789f; 121 item.Info = new TestClass { Name = "李四", Age = 22, Birthday = new DateTime(1995, 05, 20), Money = 1234 }; 122 123 string webJson = SystemWebJson(item); 124 Console.WriteLine(webJson); 125 Console.WriteLine(); 126 127 string json = Newtonsoft.Json.JsonConvert.SerializeObject(item); 128 Console.WriteLine(json); 129 Console.WriteLine(); 130 131 132 object obj = null; 133 TestClass reObj = null; 134 DateTime beginTime = DateTime.Now; 135 for (int i = 0; i < 100000; i++) 136 { 137 reObj = Newtonsoft.Json.JsonConvert.DeserializeObject<TestClass>(webJson); 138 } 139 DateTime endTime = DateTime.Now; 140 Console.WriteLine(@"耗时: " + (endTime - beginTime).TotalMilliseconds); 141 Console.WriteLine(reObj.Birthday.ToString("yyyy-MM-dd HH:mm:ss fffffff")); 142 Console.WriteLine(reObj); 143 } 144 145 146 [Test] 147 public void TestSerializeObject() 148 { 149 TestClass item = new TestClass(); 150 item.Name = "\\张三'\"'''AAB\r\nBCC\"\"\""; 151 item.Age = 24; 152 item.Birthday = new DateTime(1993, 04, 15, 10, 20, 35, 887); 153 item.Money = 123456789012345678901234567890123456789f; 154 item.Info = new TestClass { Name = "李四", Age = 22, Birthday = new DateTime(1995, 05, 20), Money = 1234 }; 155 156 string json = null; 157 DateTime beginTime = DateTime.Now; 158 for (int i = 0; i < 100000; i++) 159 { 160 json = JsonHelper.JsonSerialize(item); 161 } 162 DateTime endTime = DateTime.Now; 163 Console.WriteLine(@"耗时: " + (endTime - beginTime).TotalMilliseconds); 164 Console.WriteLine(json); 165 } 166 [Test] 167 public void TestSerializeObject2() 168 { 169 TestClass item = new TestClass(); 170 item.Name = "\\张三'\"'''AAB\r\nBCC\"\"\""; 171 item.Age = 24; 172 item.Birthday = new DateTime(1993, 04, 15, 10, 20, 35, 887); 173 item.Money = 123456789012345678901234567890123456789f; 174 item.Info = new TestClass { Name = "李四", Age = 22, Birthday = new DateTime(1995, 05, 20), Money = 1234 }; 175 176 string json = null; 177 DateTime beginTime = DateTime.Now; 178 for (int i = 0; i < 100000; i++) 179 { 180 json = Newtonsoft.Json.JsonConvert.SerializeObject(item); 181 } 182 DateTime endTime = DateTime.Now; 183 Console.WriteLine(@"耗时: " + (endTime - beginTime).TotalMilliseconds); 184 Console.WriteLine(json); 185 } 186 187 188 189 190 191 192 193 [Test] 194 public void TestArray() 195 { 196 Console.WriteLine(typeof(string[])); 197 Console.WriteLine(Array.CreateInstance(typeof(string), 0)); 198 Console.WriteLine(typeof(List<>).IsGenericTypeDefinition); //true 199 Console.WriteLine(typeof(List<string>).IsGenericTypeDefinition); //false 200 Console.WriteLine(typeof(IList<>).IsAssignableFrom(typeof(List<>))); 201 Console.WriteLine(typeof(IList<>).IsAssignableFrom(typeof(List<string>))); 202 203 Console.WriteLine(typeof(IList).IsAssignableFrom(typeof(List<string>))); 204 Console.WriteLine(typeof(List<>).IsAssignableFrom(typeof(List<string>))); 205 206 Console.WriteLine(typeof(IList).IsAssignableFrom(typeof(TestListClass))); //true 207 Console.WriteLine(typeof(IList<>).IsAssignableFrom(typeof(TestListClass))); //false 208 209 Console.WriteLine(typeof(TestListClass).GetGenericArguments().Length); //0 210 Console.WriteLine(JsonList.GetListElementType(typeof(TestListClass))); //0 211 Console.WriteLine(typeof(string[]).GetElementType()); //0 212 213 214 } 215 [Test] 216 public void TestTimeStamp() 217 { 218 DateTime time = Convert.ToDateTime("1993-04-15T10:20:35.987654321"); 219 long stamp = JsonHelper.DateTimeToStamp(time); 220 DateTime time2 = JsonHelper.StampToDateTime(stamp); 221 222 Console.WriteLine(time.ToString("yyyy-MM-dd HH:mm:ss fffffff")); 223 Console.WriteLine(time2.ToString("yyyy-MM-dd HH:mm:ss fffffff")); 224 } 225 [Test] 226 public void TestStringReader() 227 { 228 StringReader reader = new StringReader(Resources.TestObjectJson2); 229 230 int len = 0; 231 while (true) 232 { 233 char c = (char)reader.Read(); 234 Console.Write(c); 235 Console.Write((char)reader.Peek()); 236 len++; 237 if (len >= 50000) 238 break; 239 } 240 } 241 242 243 244 private string SystemWebJson(object obj) 245 { 246 JavaScriptSerializer ser = new JavaScriptSerializer(); 247 string json = ser.Serialize(obj); 248 return json; 249 } 250 251 252 public class TestClass 253 { 254 public string Name { get; set; } 255 public int Age { get; set; } 256 public DateTime Birthday { get; set; } 257 public TestClass Info { get; set; } 258 public float Money { get; set; } 259 260 } 261 public class TestListClass : List<string> 262 { 263 264 } 265 266 } 267 268 269 270 }
相关思考:
其实,不想用 Newtonsoft.Json.dll 的最大原因是:自己的框架 不想引用太多 第三方的东西,能完全独立最好。
而且,自己的一个框架 100KB,引用一个 400KB 的 Newtonsoft.Json.dll —— 会让人觉得:你的框架70% 的功能都是 Newtonsoft.Json.dll 实现的,你只是做了个封装而已。
如何技能保证 框架的独立性,又能利用到 Newtonsoft.Json.dll 的性能呢?
方案如下:
> 启用 Emit 高速反射 (性能逼近 原生调用)
> 调用 JsonHelper 时,先尝试反射 Newtonsoft.Json.dll 是否存在,如果存在 就用 Emit 调用 Newtonsoft.Json.dll
> 如果不存在,则使用 JsonHelper 的自带算法。
> 这样,似乎就能达到 想要的目的。
代码 1300行 就实现了 Json算法,但是 没啥技术含量 和 实用通用含量(可能小众用户用得到) —— 不敢发布到 博客园首页。
InkFx
2017-11-24 23:42
---------------------------------------------------------------------------------------------------------------------------------------------------
2018-08-08,将之前的 字符串解析算法 的核心函数,替换成了 新写的 栈结构字符串解析算法。
—— 性能直接逼近 Json.Net (Json.Net 之前测试的是 10W次 3.7秒, 之前的解析算法是 10W次 12秒 —— 这次的新算法是 4.2秒)
---------------------------------------------------------------------------------------------------------------------------------------------------
什么是 栈结构字符串:
> 具备嵌套逻辑的 字符串, Xml、Json、PDF的属性串 都属于 栈结构的字符串
> 这次,是因为 有这样一段 PDF属性串需要解析 —— 如果像之前的 JsonHelper 那样,写专用解析算法 特别废脑细胞【桌子一拍,劳资要写一个 通用栈结构字符串解析算法】。
Json 结构:
1 { 2 3 "age":52, 4 5 "name":"Jim \u0027\u0027\u6211\u7231\u4f60\u000d\u000aABC |||| \u2A6D6 Carrey \"Love\" :[],{} AAA \'CCC\' ", 6 7 "jsnFO":{ 8 9 "age":76, 10 11 "name":"Morgan Freeman \"Love\" :[],{} AAA \'CCC\' ", 12 13 "jsnSO":{ 14 15 "age":83, 16 17 "name":"Clint Eastwood \"Love\" :[],{} AAA \'CCC\' ", 18 19 "jsnTO":{ 20 21 "age":81, 22 23 "name":"Michael Caine \"Love\" :[],{} AAA \'CCC\' ", 24 25 "messages":[ 26 27 "You wouldn't hit a man..", 28 29 "At this point, I'd set you..", 30 31 "You know, your bobby dangler.." 32 33 ] 34 35 }, 36 37 "messages":[ 38 39 "This is the AK-47 assault..", 40 41 "Are you feeling lucky.. \"Love\" :[],{} AAA \'CCC\' Are you feeling lucky.. \"Love\" :[],{} AAA \'CCC\' FCD", 42 43 "When a naked man's chasing a.." 44 45 ] 46 47 }, 48 49 "messages":[ 50 51 "I once heard a wise man..", 52 53 "Well, what is it today? More..", 54 55 "Bruce... I'm God. Circumstances have.. \"Love\" :[],{} AAA \'CCC\' " 56 57 ] 58 59 }, 60 61 "messages":[ 62 63 "Hey, maybe I will give you a call.. \"Love\" :[],{} AAA \'CCC\' ", 64 65 "Excuse me, I'd like to ask you a few..", 66 67 "Brain freeze. Alrighty Then I just heard.." 68 69 ] 70 71 }
PDF属性串:
1 <</Type/Page/MediaBox [0 0 595 842] 2 /Rotate 0/Parent 3 0 R 3 /Resources<</ProcSet[/PDF /Text] 4 /ExtGState 14 0 R 5 /Font 15 0 R 6 >> 7 /Contents 5 0 R 8 >>
1 <</Limits[(wl2)(wl48)] 2 Names[(wl2) 337 0 R 3 (wl20) 355 0 R 4 (wl21) 356 0 R 5 (wl22) 357 0 R 6 (wl23) 358 0 R 7 (wl24) 359 0 R 8 (wl25) 360 0 R 9 (wl26) 361 0 R 10 (wl27) 362 0 R 11 (wl28) 363 0 R 12 (wl29) 364 0 R 13 (wl3) 338 0 R 14 (wl30) 365 0 R 15 (wl31) 366 0 R 16 (wl32) 367 0 R 17 (wl33) 368 0 R 18 (wl34) 369 0 R 19 (wl35) 370 0 R 20 (wl36) 371 0 R 21 (wl37) 372 0 R 22 (wl38) 373 0 R 23 (wl39) 374 0 R 24 (wl4) 339 0 R 25 (wl40) 375 0 R 26 (wl41) 376 0 R 27 (wl42) 377 0 R 28 (wl43) 378 0 R 29 (wl44) 379 0 R 30 (wl45) 380 0 R 31 (wl46) 381 0 R 32 (wl47) 382 0 R 33 (wl48) 383 0 R 34 ] 35 >>
栈结构字符串解析算法 的 调用方式:
1 //创建一个 栈结构字符串 解析方案 2 StrStack stack = new StrStack(); 3 stack.RemoveEmptyAndLineEnd = true; 4 stack.SetHasChildRule('{', '}', null); 5 stack.SetHasChildRule('[', ']', null); 6 stack.SetNoChildRule('"', '"', (l, i, c, s) => { return i <= 0 || l[i - 1] != '\\'; }); 7 stack.SetNoChildRule('\'', '\'', (l, i, c, s) => { return i <= 0 || l[i - 1] != '\\'; }); 8 stack.SetConstRule("null", null); 9 stack.SetConstRule("true", null); 10 stack.SetConstRule("false", null); 11 stack.SetNumericRule(); 12 stack.SetCharRule(';', null); 13 stack.SetCharRule(',', null); 14 stack.SetCharRule(':', null); 15 16 //通过方案, 解析出所有 栈结构对象(包括嵌套逻辑) 17 List<StrStackObject> listItem = stack.Analyze(str); 18 StrStackObject item = listItem[0]; 19 20 //栈对象 和 嵌套逻辑有了, 接下来就是转换成 自己的 Json算法对象、 PDF算法对象了...