You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2629 lines
103 KiB

2 years ago
4 years ago
4 years ago
4 years ago
5 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
5 years ago
5 years ago
2 years ago
2 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
2 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
3 years ago
3 years ago
3 years ago
5 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
3 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
3 years ago
5 years ago
5 years ago
5 years ago
2 years ago
5 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
5 years ago
2 years ago
5 years ago
4 years ago
4 years ago
5 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
2 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
  1. using Newtonsoft.Json;
  2. using Newtonsoft.Json.Linq;
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Collections.Specialized;
  7. #if !NET20
  8. using System.Dynamic;
  9. using System.IO;
  10. #endif
  11. using System.Reflection;
  12. using static Apewer.NumberUtility;
  13. using static Apewer.RuntimeUtility;
  14. namespace Apewer
  15. {
  16. /// <summary>Json。</summary>
  17. [Serializable]
  18. public sealed class Json
  19. #if !NET20
  20. : DynamicObject
  21. #endif
  22. {
  23. #region 配置。
  24. [NonSerialized]
  25. private static bool _throw = false;
  26. [NonSerialized]
  27. private static bool _recursively = true;
  28. [NonSerialized]
  29. private static bool _forceall = true;
  30. /// <summary>允许抛出 Exception,默认为不允许。</summary>
  31. public static bool AllowException { get { return _throw; } set { _throw = value; } }
  32. /// <summary>当存在递归引用时候包含递归项。指定为 True 时递归项为 Null 值,指定为 False 时不包含递归项。默认值:False。</summary>
  33. public static bool AllowRecursively { get { return _recursively; } set { _recursively = value; } }
  34. /// <summary>将所有类型视为拥有 <see cref="SerializableAttribute" /> 特性。</summary>
  35. /// <remarks>默认值:FALSE。</remarks>
  36. public static bool ForceAll { get => _forceall; set => _forceall = value; }
  37. #endregion
  38. #region 消息
  39. private const string ValueIsNotSupported = "指定的值类型不受支持";
  40. private const string IsNotJsonObject = "当前实例不是 Json 对象。";
  41. private const string IsNotJsonArray = "当前实例不是 Json 数组。";
  42. private const string InvalidIndex = "未指定有效的索引。";
  43. private const string IndexLessZero = "指定的索引小于 0,无效。";
  44. private const string IndexGraterMax = "指定的索引超出了最大值,无效。";
  45. private const string IndexGraterCount = "指定的索引超出了数量,无效。";
  46. #endregion
  47. #region JToken
  48. [NonSerialized]
  49. private JToken _jtoken = null;
  50. [NonSerialized]
  51. private JArray _jarray = null;
  52. [NonSerialized]
  53. private JObject _jobject = null;
  54. [NonSerialized]
  55. private JProperty _jproperty = null;
  56. [NonSerialized]
  57. private JValue _jvalue = null;
  58. static JToken ToJToken(object value)
  59. {
  60. if (value == null) return new JValue(null, JTokenType.Null);
  61. var type = value.GetType();
  62. if (RuntimeUtility.IsNullableType(type)) value = RuntimeUtility.GetNullableValue(value);
  63. if (value == null) return new JValue(null, JTokenType.Null);
  64. if (value is Json json) return json?._jtoken ?? new JValue(null, JTokenType.Null);
  65. if (value is DateTime dt) return new JValue(SerializeDateTime(dt));
  66. if (value is byte[] bytes) return new JValue(SerializeBytes(bytes));
  67. if (value is string) return new JValue(value);
  68. if (value is bool) return new JValue(value);
  69. if (value is byte) return new JValue(value);
  70. if (value is sbyte) return new JValue(value);
  71. if (value is short) return new JValue(value);
  72. if (value is ushort) return new JValue(value);
  73. if (value is int) return new JValue(value);
  74. if (value is uint) return new JValue(value);
  75. if (value is long) return new JValue(value);
  76. if (value is ulong uint64) return (uint64 > int.MaxValue) ? new JValue(uint64.ToString()) : new JValue(Convert.ToInt64(uint64));
  77. if (value is float) return new JValue(value);
  78. if (value is double) return new JValue(value);
  79. if (value is decimal) return new JValue(value);
  80. var from = From(value);
  81. if (from != null) return from._jtoken;
  82. throw new ArgumentException(ValueIsNotSupported);
  83. }
  84. static object ParseJToken(JToken jtoken)
  85. {
  86. if (jtoken == null) return null;
  87. if (jtoken is JValue jvalue) return jvalue.Value;
  88. if (jtoken is JObject) return new Json(jtoken);
  89. if (jtoken is JArray) return new Json(jtoken);
  90. if (jtoken is JProperty jproperty)
  91. {
  92. var value = jproperty.Value;
  93. if (value == null) return null;
  94. return ParseJToken(value);
  95. }
  96. throw new InvalidOperationException($"Json 类型 {jtoken.Type} 不支持解析。");
  97. }
  98. #endregion
  99. #region 构造。
  100. #region Reset
  101. /// <summary>重置当前对象为空。</summary>
  102. public void Reset()
  103. {
  104. Construct();
  105. }
  106. /// <summary>使用指定的文本重置当前对象。</summary>
  107. public bool Reset(string json)
  108. {
  109. Construct();
  110. if (json == null)
  111. {
  112. if (AllowException) throw new ArgumentNullException("json", "参数无效。");
  113. return false;
  114. }
  115. var parsed = From(json);
  116. if (parsed == null) return false;
  117. Construct(parsed._jtoken);
  118. return true;
  119. }
  120. /// <summary>使用指定的对象重置当前对象。</summary>
  121. /// <exception cref="System.Exception"></exception>
  122. /// <exception cref="System.ArgumentNullException"></exception>
  123. public bool Reset(Json json)
  124. {
  125. Construct();
  126. if (json == null)
  127. {
  128. if (AllowException) throw new ArgumentNullException("json", "参数无效。");
  129. return false;
  130. }
  131. var parsed = From(json.ToString());
  132. if (parsed == null) return false;
  133. Construct(parsed._jtoken);
  134. return true;
  135. }
  136. /// <summary>使用指定的字典对象重置当前对象。</summary>
  137. /// <exception cref="System.Exception"></exception>
  138. /// <exception cref="System.ArgumentNullException"></exception>
  139. public bool Reset(Dictionary<string, string> dictionary)
  140. {
  141. Construct();
  142. if (dictionary == null)
  143. {
  144. if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。");
  145. return false;
  146. }
  147. var json = NewObject();
  148. foreach (var item in dictionary) json[item.Key] = item.Value;
  149. Construct(json._jtoken);
  150. return true;
  151. }
  152. /// <summary>使用指定的文本字典对象重置当前对象。</summary>
  153. /// <exception cref="System.Exception"></exception>
  154. /// <exception cref="System.ArgumentNullException"></exception>
  155. public bool Reset(TextSet dictionary)
  156. {
  157. Construct();
  158. if (dictionary == null)
  159. {
  160. if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。");
  161. return false;
  162. }
  163. return Reset(dictionary.Origin);
  164. }
  165. /// <summary>使用指定的文本字典对象重置当前对象。</summary>
  166. /// <exception cref="System.Exception"></exception>
  167. /// <exception cref="System.ArgumentNullException"></exception>
  168. public bool Reset(ObjectSet<string> dictionary)
  169. {
  170. Construct();
  171. if (dictionary == null)
  172. {
  173. if (AllowException) throw new ArgumentNullException("dictionary", "参数无效。");
  174. return false;
  175. }
  176. return Reset(dictionary.Origin);
  177. }
  178. #endregion
  179. private void Construct(JToken jtoken = null)
  180. {
  181. _jtoken = jtoken;
  182. _jarray = null;
  183. _jobject = null;
  184. _jproperty = null;
  185. _jvalue = null;
  186. if (_jtoken != null)
  187. {
  188. if (_jtoken is JArray) _jarray = (JArray)_jtoken;
  189. if (_jtoken is JObject) _jobject = (JObject)_jtoken;
  190. if (_jtoken is JProperty) _jproperty = (JProperty)_jtoken;
  191. if (_jtoken is JValue) _jvalue = (JValue)_jtoken;
  192. }
  193. }
  194. private Json(JToken jtoken)
  195. {
  196. Construct(jtoken);
  197. }
  198. /// <summary>创建 Json Object 实例。</summary>
  199. public Json()
  200. {
  201. Construct(new JObject());
  202. }
  203. #endregion
  204. #region 属性。
  205. /// <summary>用于兼容 SimpleJson 的操作。</summary>
  206. public string this[string name] { get => GetProperty(name)?.ToString() ?? ""; set => SetProperty(name, value ?? ""); }
  207. /// <summary>获取或设置数组的元素。</summary>
  208. public object this[int index] { get => GetItem(index); set => SetItem(index, value); }
  209. private JTokenType TokenType
  210. {
  211. get
  212. {
  213. if (_jtoken == null) return JTokenType.None;
  214. else return _jtoken.Type;
  215. //if (_jtoken == null) return 0;
  216. //switch (_jtoken.Type)
  217. //{
  218. // case JTokenType.None: return 0;
  219. // case JTokenType.Object: return 1;
  220. // case JTokenType.Array: return 2;
  221. // case JTokenType.Constructor: return 3;
  222. // case JTokenType.Property: return 4;
  223. // case JTokenType.Comment: return 5;
  224. // case JTokenType.Integer: return 6;
  225. // case JTokenType.Float: return 7;
  226. // case JTokenType.String: return 8;
  227. // case JTokenType.Boolean: return 9;
  228. // case JTokenType.Null: return 10;
  229. // case JTokenType.Undefined: return 11;
  230. // case JTokenType.Date: return 12;
  231. // case JTokenType.Raw: return 13;
  232. // case JTokenType.Bytes: return 14;
  233. // case JTokenType.Guid: return 15;
  234. // case JTokenType.Uri: return 16;
  235. // case JTokenType.TimeSpan: return 17;
  236. // default: return 0;
  237. //}
  238. }
  239. }
  240. /// <summary>
  241. /// <para>获取当前实例的类型。可能的类型:</para>
  242. /// <para>None Object Array Constructor Property Comment Integer Float String</para>
  243. /// <para>Boolean Null Undefined Date Raw Bytes Guid Uri TimeSpan</para>
  244. /// </summary>
  245. public string Type { get { return TokenType.ToString(); } }
  246. /// <summary>实例有效。</summary>
  247. public bool Available { get { return _jtoken != null && TokenType != JTokenType.None; } }
  248. /// <summary>获取当前实例的值,当为 Json 格式时缩进。</summary>
  249. public string Lucid { get { return ToString(true); } }
  250. /// <summary>获取当前实例的值,当为 Json 格式时不缩进。</summary>
  251. public string Text { get { return ToString(false); } }
  252. /// <summary>当前实例类型为 Property 时,获取名称。</summary>
  253. public string Name
  254. {
  255. get { return _jproperty == null ? null : _jproperty.Name; }
  256. }
  257. /// <summary>获取值。</summary>
  258. public object Value
  259. {
  260. get
  261. {
  262. if (_jvalue != null)
  263. {
  264. if (_jvalue.Value == null) return null;
  265. if (_jvalue.Value is JValue jvalue) return jvalue.Value;
  266. if (_jvalue.Value is JToken jtoken) return new Json(jtoken);
  267. else return _jvalue.Value;
  268. }
  269. if (_jproperty != null)
  270. {
  271. if (_jproperty.Value == null) return null;
  272. if (_jproperty.Value is JValue jvalue) return jvalue.Value;
  273. if (_jproperty.Value is JToken jtoken) return new Json(jtoken);
  274. else return _jproperty.Value;
  275. }
  276. return null;
  277. }
  278. }
  279. /// <summary>实例无效。</summary>
  280. public bool IsNull { get { return _jtoken == null; } }
  281. #endregion
  282. #region Private Get
  283. private Json[] PrivateGetProperties { get { return GetProperties(); } }
  284. private Json[] PrivateGetValues { get { return GetValues(); } }
  285. private Json[] PrivateGetObjects { get { return GetObjects(); } }
  286. private Json[] PrivateGetItems { get { return GetItems(); } }
  287. #endregion
  288. #region Object : Get/Set
  289. /// <summary>获取所有类型为 Property 的子项。</summary>
  290. public Json[] GetProperties()
  291. {
  292. var ab = new ArrayBuilder<Json>();
  293. if (_jobject != null)
  294. {
  295. var children = _jobject.Children();
  296. foreach (var child in children)
  297. {
  298. var json = new Json(child);
  299. ab.Add(json);
  300. }
  301. }
  302. return ab.Export();
  303. }
  304. /// <summary>当前实例类型为 Object 时搜索属性,失败时返回 Null。</summary>
  305. /// <param name="name">将要搜索的属性名称,不可为 Null。</param>
  306. /// <exception cref="System.ArgumentNullException"></exception>
  307. /// <exception cref="System.InvalidOperationException"></exception>
  308. public Json GetProperty(string name)
  309. {
  310. if (_jobject == null || TokenType != JTokenType.Object)
  311. {
  312. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  313. return null;
  314. }
  315. if (name == null)
  316. {
  317. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  318. return null;
  319. }
  320. var children = _jtoken.Children<JProperty>();
  321. foreach (var child in children)
  322. {
  323. if (child.Name == name)
  324. {
  325. var json = new Json(child.Value);
  326. return json;
  327. }
  328. }
  329. return null;
  330. }
  331. /// <summary>当前实例类型为 Object 时添加属性,值为 Null,已存在的属性将被替换。</summary>
  332. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  333. /// <exception cref="System.ArgumentNullException"></exception>
  334. /// <exception cref="System.InvalidOperationException"></exception>
  335. public bool SetProperty(string name)
  336. {
  337. if (_jobject == null || TokenType != JTokenType.Object)
  338. {
  339. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  340. return false;
  341. }
  342. if (name == null)
  343. {
  344. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  345. return false;
  346. }
  347. var children = _jobject.Children<JProperty>();
  348. foreach (var child in children)
  349. {
  350. if (child.Name == name)
  351. {
  352. _jobject.Remove(name);
  353. break;
  354. }
  355. }
  356. _jobject.Add(name, null);
  357. return true;
  358. }
  359. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  360. /// <param name="property">将要添加的属性。</param>
  361. /// <exception cref="System.ArgumentException"></exception>
  362. /// <exception cref="System.ArgumentNullException"></exception>
  363. /// <exception cref="System.InvalidOperationException"></exception>
  364. public bool SetProperty(Json property)
  365. {
  366. if (_jobject == null || TokenType != JTokenType.Object)
  367. {
  368. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  369. return false;
  370. }
  371. if (property == null)
  372. {
  373. if (_throw) throw new ArgumentNullException("property", "参数无效。");
  374. return false;
  375. }
  376. if (property._jproperty == null || property.TokenType != JTokenType.Property)
  377. {
  378. if (_throw) throw new ArgumentException("property", "将要设置的属性无效。");
  379. return false;
  380. }
  381. var name = property._jproperty.Name;
  382. var children = _jobject.Children<JProperty>();
  383. foreach (var child in children)
  384. {
  385. if (child.Name == name)
  386. {
  387. _jobject.Remove(name);
  388. break;
  389. }
  390. }
  391. _jobject.Add(name, property._jtoken);
  392. return true;
  393. }
  394. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  395. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  396. /// <param name="value">将要添加的属性值。</param>
  397. /// <exception cref="System.ArgumentNullException"></exception>
  398. /// <exception cref="System.InvalidOperationException"></exception>
  399. public bool SetProperty(string name, bool value)
  400. {
  401. if (_jobject == null || TokenType != JTokenType.Object)
  402. {
  403. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  404. return false;
  405. }
  406. if (name == null)
  407. {
  408. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  409. return false;
  410. }
  411. var children = _jobject.Children<JProperty>();
  412. foreach (var child in children)
  413. {
  414. if (child.Name == name)
  415. {
  416. _jobject.Remove(name);
  417. break;
  418. }
  419. }
  420. _jobject.Add(name, value);
  421. return true;
  422. }
  423. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  424. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  425. /// <param name="value">将要添加的属性值。</param>
  426. /// <exception cref="System.ArgumentNullException"></exception>
  427. /// <exception cref="System.InvalidOperationException"></exception>
  428. public bool SetProperty(string name, string value)
  429. {
  430. if (_jobject == null || TokenType != JTokenType.Object)
  431. {
  432. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  433. return false;
  434. }
  435. if (name == null)
  436. {
  437. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  438. return false;
  439. }
  440. var children = _jobject.Children<JProperty>();
  441. foreach (var child in children)
  442. {
  443. if (child.Name == name)
  444. {
  445. _jobject.Remove(name);
  446. break;
  447. }
  448. }
  449. _jobject.Add(name, value);
  450. return true;
  451. }
  452. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  453. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  454. /// <param name="value">将要添加的属性值。</param>
  455. /// <exception cref="System.ArgumentNullException"></exception>
  456. /// <exception cref="System.InvalidOperationException"></exception>
  457. public bool SetProperty(string name, int value)
  458. {
  459. if (_jobject == null || TokenType != JTokenType.Object)
  460. {
  461. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  462. return false;
  463. }
  464. if (name == null)
  465. {
  466. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  467. return false;
  468. }
  469. var children = _jobject.Children<JProperty>();
  470. foreach (var child in children)
  471. {
  472. if (child.Name == name)
  473. {
  474. _jobject.Remove(name);
  475. break;
  476. }
  477. }
  478. _jobject.Add(name, value);
  479. return true;
  480. }
  481. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  482. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  483. /// <param name="value">将要添加的属性值。</param>
  484. /// <exception cref="System.ArgumentNullException"></exception>
  485. /// <exception cref="System.InvalidOperationException"></exception>
  486. public bool SetProperty(string name, long value)
  487. {
  488. if (_jobject == null || TokenType != JTokenType.Object)
  489. {
  490. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  491. return false;
  492. }
  493. if (name == null)
  494. {
  495. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  496. return false;
  497. }
  498. var children = _jobject.Children<JProperty>();
  499. foreach (var child in children)
  500. {
  501. if (child.Name == name)
  502. {
  503. _jobject.Remove(name);
  504. break;
  505. }
  506. }
  507. _jobject.Add(name, value);
  508. return true;
  509. }
  510. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  511. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  512. /// <param name="value">将要添加的属性值。</param>
  513. /// <exception cref="System.ArgumentNullException"></exception>
  514. /// <exception cref="System.InvalidOperationException"></exception>
  515. public bool SetProperty(string name, float value)
  516. {
  517. if (_jobject == null || TokenType != JTokenType.Object)
  518. {
  519. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  520. return false;
  521. }
  522. if (name == null)
  523. {
  524. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  525. return false;
  526. }
  527. var children = _jobject.Children<JProperty>();
  528. foreach (var child in children)
  529. {
  530. if (child.Name == name)
  531. {
  532. _jobject.Remove(name);
  533. break;
  534. }
  535. }
  536. _jobject.Add(name, value);
  537. return true;
  538. }
  539. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  540. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  541. /// <param name="value">将要添加的属性值。</param>
  542. /// <exception cref="System.ArgumentNullException"></exception>
  543. /// <exception cref="System.InvalidOperationException"></exception>
  544. public bool SetProperty(string name, double value)
  545. {
  546. if (_jobject == null || TokenType != JTokenType.Object)
  547. {
  548. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  549. return false;
  550. }
  551. if (name == null)
  552. {
  553. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  554. return false;
  555. }
  556. var children = _jobject.Children<JProperty>();
  557. foreach (var child in children)
  558. {
  559. if (child.Name == name)
  560. {
  561. _jobject.Remove(name);
  562. break;
  563. }
  564. }
  565. _jobject.Add(name, value);
  566. return true;
  567. }
  568. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  569. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  570. /// <param name="value">将要添加的属性值。</param>
  571. /// <exception cref="System.ArgumentNullException"></exception>
  572. /// <exception cref="System.InvalidOperationException"></exception>
  573. public bool SetProperty(string name, decimal value)
  574. {
  575. if (_jobject == null || TokenType != JTokenType.Object)
  576. {
  577. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  578. return false;
  579. }
  580. if (name == null)
  581. {
  582. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  583. return false;
  584. }
  585. var children = _jobject.Children<JProperty>();
  586. foreach (var child in children)
  587. {
  588. if (child.Name == name)
  589. {
  590. _jobject.Remove(name);
  591. break;
  592. }
  593. }
  594. _jobject.Add(name, value);
  595. return true;
  596. }
  597. /// <summary>当前实例类型为 Object 时添加属性,已存在的属性将被替换。</summary>
  598. /// <param name="name">将要添加的属性名称,不可为 Null。</param>
  599. /// <param name="value">将要添加的属性值。</param>
  600. /// <exception cref="System.ArgumentException"></exception>
  601. /// <exception cref="System.ArgumentNullException"></exception>
  602. /// <exception cref="System.InvalidOperationException"></exception>
  603. public bool SetProperty(string name, Json value)
  604. {
  605. if (_jobject == null || TokenType != JTokenType.Object)
  606. {
  607. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  608. return false;
  609. }
  610. if (name == null)
  611. {
  612. if (_throw) throw new ArgumentNullException("name", "参数无效。");
  613. return false;
  614. }
  615. var children = _jobject.Children<JProperty>();
  616. foreach (var child in children)
  617. {
  618. if (child.Name == name)
  619. {
  620. _jobject.Remove(name);
  621. break;
  622. }
  623. }
  624. if (value == null)
  625. {
  626. _jobject.Add(name, null);
  627. }
  628. else
  629. {
  630. if (value._jtoken == null)
  631. {
  632. _jobject.Add(name, null);
  633. }
  634. else
  635. {
  636. _jobject.Add(name, value._jtoken);
  637. }
  638. }
  639. return true;
  640. }
  641. #endregion
  642. #region Array
  643. /// <summary>获取所有类型为 Value 的子项。</summary>
  644. public Json[] GetValues()
  645. {
  646. var ab = new ArrayBuilder<Json>();
  647. if (_jarray != null)
  648. {
  649. var children = _jarray.Children<JValue>();
  650. foreach (var child in children)
  651. {
  652. var json = new Json(child);
  653. ab.Add(json);
  654. }
  655. }
  656. return ab.Export();
  657. }
  658. /// <summary>获取所有类型为 Object 的子项。</summary>
  659. public Json[] GetObjects()
  660. {
  661. var ab = new ArrayBuilder<Json>();
  662. if (_jarray != null)
  663. {
  664. var children = _jarray.Children<JObject>();
  665. foreach (var child in children)
  666. {
  667. var json = new Json(child);
  668. ab.Add(json);
  669. }
  670. }
  671. return ab.Export();
  672. }
  673. /// <summary>获取 Array 中的所有元素。</summary>
  674. public Json[] GetItems()
  675. {
  676. var ab = new ArrayBuilder<Json>();
  677. if (_jarray != null)
  678. {
  679. var children = _jarray.Children();
  680. foreach (var child in children)
  681. {
  682. var json = new Json(child);
  683. ab.Add(json);
  684. }
  685. }
  686. return ab.Export();
  687. }
  688. /// <summary>当前实例类型为 Array 时添加 Null 元素。</summary>
  689. /// <exception cref="System.InvalidOperationException"></exception>
  690. public bool AddItem()
  691. {
  692. if (_jarray == null || TokenType != JTokenType.Array)
  693. {
  694. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  695. return false;
  696. }
  697. _jarray.Add(JValue.CreateNull());
  698. return true;
  699. }
  700. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  701. /// <param name="json">将要添加的元素。</param>
  702. /// <exception cref="System.InvalidOperationException"></exception>
  703. public bool AddItem(Json json)
  704. {
  705. if (json == null)
  706. {
  707. return AddItem();
  708. }
  709. if (_jarray == null || TokenType != JTokenType.Array)
  710. {
  711. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  712. return false;
  713. }
  714. if (json._jtoken == null || json.TokenType == JTokenType.None)
  715. {
  716. if (_throw) throw new ArgumentException("json", "将要设置的元素无效。");
  717. return false;
  718. }
  719. _jarray.Add(json._jtoken);
  720. return true;
  721. }
  722. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  723. /// <param name="value">将要添加的元素。</param>
  724. /// <exception cref="System.InvalidOperationException"></exception>
  725. public bool AddItem(string value)
  726. {
  727. if (_jarray == null || TokenType != JTokenType.Array)
  728. {
  729. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  730. return false;
  731. }
  732. _jarray.Add(value ?? "");
  733. return true;
  734. }
  735. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  736. /// <param name="value">将要添加的元素。</param>
  737. /// <exception cref="System.InvalidOperationException"></exception>
  738. public bool AddItem(bool value)
  739. {
  740. if (_jarray == null || TokenType != JTokenType.Array)
  741. {
  742. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  743. return false;
  744. }
  745. _jarray.Add(value);
  746. return true;
  747. }
  748. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  749. /// <param name="value">将要添加的元素。</param>
  750. /// <exception cref="System.InvalidOperationException"></exception>
  751. public bool AddItem(int value)
  752. {
  753. if (_jarray == null || TokenType != JTokenType.Array)
  754. {
  755. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  756. return false;
  757. }
  758. _jarray.Add(value);
  759. return true;
  760. }
  761. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  762. /// <param name="value">将要添加的元素。</param>
  763. /// <exception cref="System.InvalidOperationException"></exception>
  764. public bool AddItem(long value)
  765. {
  766. if (_jarray == null || TokenType != JTokenType.Array)
  767. {
  768. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  769. return false;
  770. }
  771. _jarray.Add(value);
  772. return true;
  773. }
  774. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  775. /// <param name="value">将要添加的元素。</param>
  776. /// <exception cref="System.InvalidOperationException"></exception>
  777. public bool AddItem(float value)
  778. {
  779. if (_jarray == null || TokenType != JTokenType.Array)
  780. {
  781. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  782. return false;
  783. }
  784. _jarray.Add(value);
  785. return true;
  786. }
  787. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  788. /// <param name="value">将要添加的元素。</param>
  789. /// <exception cref="System.InvalidOperationException"></exception>
  790. public bool AddItem(double value)
  791. {
  792. if (_jarray == null || TokenType != JTokenType.Array)
  793. {
  794. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  795. return false;
  796. }
  797. _jarray.Add(value);
  798. return true;
  799. }
  800. /// <summary>当前实例类型为 Array 时添加元素。</summary>
  801. /// <param name="value">将要添加的元素。</param>
  802. /// <exception cref="System.InvalidOperationException"></exception>
  803. public bool AddItem(decimal value)
  804. {
  805. if (_jarray == null || TokenType != JTokenType.Array)
  806. {
  807. if (_throw) throw new InvalidOperationException("当前实例不支持元素。");
  808. return false;
  809. }
  810. _jarray.Add(value);
  811. return true;
  812. }
  813. /// <summary>从 Parent 中移除。</summary>
  814. /// <exception cref="System.InvalidOperationException"></exception>
  815. /// <exception cref="ArgumentOutOfRangeException"></exception>
  816. public bool Remove()
  817. {
  818. if (_jtoken == null) return false;
  819. if (_jtoken.Parent == null)
  820. {
  821. if (_throw) throw new InvalidOperationException("Parent 对象丢失。");
  822. return false;
  823. }
  824. try
  825. {
  826. _jtoken.Remove();
  827. return true;
  828. }
  829. catch (Exception exception)
  830. {
  831. if (_throw) throw exception;
  832. return false;
  833. }
  834. }
  835. /// <summary>获取数组的元素。</summary>
  836. /// <exception cref="ArgumentOutOfRangeException" />
  837. /// <exception cref="InvalidOperationException" />
  838. public object GetItem(int index)
  839. {
  840. if (!IsArray) throw new InvalidOperationException(IsNotJsonArray);
  841. if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), IndexLessZero);
  842. var jarray = _jtoken as JArray;
  843. if (index >= jarray.Count) throw new ArgumentOutOfRangeException(nameof(index), IndexGraterCount);
  844. var item = jarray[index];
  845. return ParseJToken(item);
  846. }
  847. /// <summary>设置数组的元素。</summary>
  848. /// <exception cref="ArgumentException" />
  849. /// <exception cref="ArgumentOutOfRangeException" />
  850. /// <exception cref="InvalidOperationException" />
  851. public void SetItem(int index, object value)
  852. {
  853. if (!IsArray) throw new InvalidOperationException(IsNotJsonArray);
  854. if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), IndexLessZero);
  855. var jarray = _jtoken as JArray;
  856. while (jarray.Count < index + 1) jarray.Add(null);
  857. var jtoken = ToJToken(value);
  858. jarray.SetItem(index, jtoken);
  859. }
  860. #endregion
  861. #region Property
  862. /// <summary>Json 对象实例为空。</summary>
  863. public bool IsNone { get { return TokenType == JTokenType.None; } }
  864. /// <summary>Json 对象为 Object 实例。</summary>
  865. public bool IsObject { get { return TokenType == JTokenType.Object; } }
  866. /// <summary>Json 对象为 Array 实例。</summary>
  867. public bool IsArray { get { return TokenType == JTokenType.Array; } }
  868. /// <summary>Json 对象为 Property 实例。</summary>
  869. public bool IsProperty { get { return TokenType == JTokenType.Property; } }
  870. /// <summary>Json 对象为 String 实例。</summary>
  871. public bool IsString { get { return TokenType == JTokenType.String; } }
  872. /// <summary>当前实例类型为 Property 时设置 Null 值。</summary>
  873. /// <exception cref="System.InvalidOperationException"></exception>
  874. public bool SetValue()
  875. {
  876. var available = _jproperty != null && TokenType == JTokenType.Property;
  877. if (!available)
  878. {
  879. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  880. return false;
  881. }
  882. _jproperty.Value = JValue.CreateNull();
  883. return true;
  884. }
  885. /// <summary>当前实例类型为 Property 时设置值。</summary>
  886. /// <param name="value">将要设置的值。</param>
  887. /// <exception cref="System.InvalidOperationException"></exception>
  888. public bool SetValue(Json value)
  889. {
  890. var available = _jproperty != null && TokenType == JTokenType.Property;
  891. if (!available)
  892. {
  893. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  894. return false;
  895. }
  896. if (value == null)
  897. {
  898. _jproperty.Value = JValue.CreateNull();
  899. return true;
  900. }
  901. if (value._jtoken == null || value.TokenType == JTokenType.None)
  902. {
  903. _jproperty.Value = JValue.CreateNull();
  904. return true;
  905. }
  906. _jproperty.Value = new JValue(value._jtoken);
  907. return true;
  908. }
  909. /// <summary>当前实例类型为 Property 时设置值。</summary>
  910. /// <param name="value">将要设置的值。</param>
  911. /// <exception cref="System.InvalidOperationException"></exception>
  912. public bool SetValue(string value)
  913. {
  914. var available = _jproperty != null && TokenType == JTokenType.Property;
  915. if (!available)
  916. {
  917. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  918. return false;
  919. }
  920. _jproperty.Value = value == null ? JValue.CreateNull() : JValue.CreateString(value);
  921. return true;
  922. }
  923. /// <summary>当前实例类型为 Property 时设置值。</summary>
  924. /// <param name="value">将要设置的值。</param>
  925. /// <exception cref="System.InvalidOperationException"></exception>
  926. public bool SetValue(bool value)
  927. {
  928. var available = _jproperty != null && TokenType == JTokenType.Property;
  929. if (!available)
  930. {
  931. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  932. return false;
  933. }
  934. _jproperty.Value = new JValue(value);
  935. return true;
  936. }
  937. /// <summary>当前实例类型为 Property 时设置值。</summary>
  938. /// <param name="value">将要设置的值。</param>
  939. /// <exception cref="System.InvalidOperationException"></exception>
  940. public bool SetValue(int value)
  941. {
  942. var available = _jproperty != null && TokenType == JTokenType.Property;
  943. if (!available)
  944. {
  945. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  946. return false;
  947. }
  948. _jproperty.Value = new JValue(value);
  949. return true;
  950. }
  951. /// <summary>当前实例类型为 Property 时设置值。</summary>
  952. /// <param name="value">将要设置的值。</param>
  953. /// <exception cref="System.InvalidOperationException"></exception>
  954. public bool SetValue(long value)
  955. {
  956. var available = _jproperty != null && TokenType == JTokenType.Property;
  957. if (!available)
  958. {
  959. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  960. return false;
  961. }
  962. _jproperty.Value = new JValue(value);
  963. return true;
  964. }
  965. /// <summary>当前实例类型为 Property 时设置值。</summary>
  966. /// <param name="value">将要设置的值。</param>
  967. /// <exception cref="System.InvalidOperationException"></exception>
  968. public bool SetValue(float value)
  969. {
  970. var available = _jproperty != null && TokenType == JTokenType.Property;
  971. if (!available)
  972. {
  973. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  974. return false;
  975. }
  976. _jproperty.Value = new JValue(value);
  977. return true;
  978. }
  979. /// <summary>当前实例类型为 Property 时设置值。</summary>
  980. /// <param name="value">将要设置的值。</param>
  981. /// <exception cref="System.InvalidOperationException"></exception>
  982. public bool SetValue(double value)
  983. {
  984. var available = _jproperty != null && TokenType == JTokenType.Property;
  985. if (!available)
  986. {
  987. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  988. return false;
  989. }
  990. _jproperty.Value = new JValue(value);
  991. return true;
  992. }
  993. /// <summary>当前实例类型为 Property 时设置值。</summary>
  994. /// <param name="value">将要设置的值。</param>
  995. /// <exception cref="System.InvalidOperationException"></exception>
  996. public bool SetValue(decimal value)
  997. {
  998. var available = _jproperty != null && TokenType == JTokenType.Property;
  999. if (!available)
  1000. {
  1001. if (_throw) throw new InvalidOperationException("当前实例不支持属性。");
  1002. return false;
  1003. }
  1004. _jproperty.Value = new JValue(value);
  1005. return true;
  1006. }
  1007. #endregion
  1008. #region Import / Export
  1009. #region String -> Json
  1010. /// <summary>解析文本为 Json 对象,失败时返回 Null。</summary>
  1011. /// <exception cref="System.Exception"></exception>
  1012. public static Json From(string text)
  1013. {
  1014. try
  1015. {
  1016. var jtoken = JToken.Parse(text);
  1017. var json = new Json(jtoken);
  1018. return json;
  1019. }
  1020. catch (Exception exception)
  1021. {
  1022. if (AllowException) throw exception;
  1023. return null;
  1024. }
  1025. }
  1026. #endregion
  1027. #region Object -> Json
  1028. /// <summary>解析实现 IList 的对象为 Json 对象,失败时返回 Null。</summary>
  1029. /// <param name="entity">将要解析的对象。</param>
  1030. /// <param name="lower">在 Json 中将属性名称转换为小写。</param>
  1031. /// <param name="depth">限制 Json 层级深度,当值小于零时将不限制深度。</param>
  1032. /// <param name="force">强制解析属性,忽略 Serializable 特性。</param>
  1033. public static Json From(IList entity, bool lower = false, int depth = -1, bool force = false)
  1034. {
  1035. if (entity == null) return null;
  1036. var recursive = new object[] { entity };
  1037. return From(entity, lower, recursive, depth, force);
  1038. }
  1039. /// <summary>解析实现 IDictionary 的对象为 Json 对象,失败时返回 Null。</summary>
  1040. /// <param name="entity">将要解析的对象。</param>
  1041. /// <param name="lower">在 Json 中将属性名称转换为小写。</param>
  1042. /// <param name="depth">限制 Json 层级深度,当值小于零时将不限制深度。</param>
  1043. /// <param name="force">强制解析属性,忽略 Serializable 特性。</param>
  1044. public static Json From(IDictionary entity, bool lower = false, int depth = -1, bool force = false)
  1045. {
  1046. if (entity == null) return null;
  1047. var recursive = new object[] { entity };
  1048. return From(entity, lower, recursive, depth, force);
  1049. }
  1050. /// <summary>
  1051. /// <para>解析对象为 Json 对象,包含所有公共属性,失败时返回 Null。</para>
  1052. /// <para>String 对象将解析文本;Json 对象将返回实例;String 对象将解析文本;实现 IDictionary 或 IList 的对象将解析内容。</para>
  1053. /// </summary>
  1054. /// <param name="entity">将要解析的对象。</param>
  1055. /// <param name="lower">在 Json 中将属性名称转换为小写。</param>
  1056. /// <param name="depth">限制 Json 层级深度,当值小于零时将不限制深度。</param>
  1057. /// <param name="force">强制解析属性,忽略 Serializable 特性。</param>
  1058. /// <exception cref="System.Exception"></exception>
  1059. public static Json From(object entity, bool lower = false, int depth = -1, bool force = false)
  1060. {
  1061. if (entity == null) return null;
  1062. var recursive = new object[] { entity };
  1063. return From(entity, lower, recursive, depth, force);
  1064. }
  1065. private static Json From(IList list, bool lower, object[] previous, int depth, bool force)
  1066. {
  1067. if (list == null) return null;
  1068. if (list is IToJson) return ((IToJson)list).ToJson();
  1069. var checker = list as IToJsonChecker;
  1070. var json = NewArray();
  1071. try
  1072. {
  1073. if (list is Array array)
  1074. {
  1075. if (array != null && array.Rank > 1)
  1076. {
  1077. ToJson(json, array, array.Rank, new int[0]);
  1078. return json;
  1079. }
  1080. }
  1081. foreach (var item in list)
  1082. {
  1083. // 由 IToJsonChecker 实现的方法检查是否包含元素。
  1084. if (checker != null && !checker.WithItemInJson(list, item)) continue;
  1085. var value = item;
  1086. // 检查递归引用。
  1087. var recursively = false;
  1088. foreach (var r in previous)
  1089. {
  1090. if (ReferenceEquals(r, value))
  1091. {
  1092. if (AllowRecursively) json.AddItem();
  1093. recursively = true;
  1094. break;
  1095. }
  1096. }
  1097. if (recursively) continue;
  1098. // value 是 null。
  1099. if (value.IsNull())
  1100. {
  1101. json.AddItem();
  1102. continue;
  1103. }
  1104. // 处理 Type 对象。
  1105. if (value.GetType().Equals(typeof(Type)) && (previous.Length > 2)) value = FullName((Type)value);
  1106. // 处理 Assembly 对象。
  1107. if (value.GetType().Equals(typeof(Assembly)) && (previous.Length > 2)) value = ((Assembly)value).FullName;
  1108. if (value == null) { json.AddItem(); }
  1109. else if (value is DateTime dt) { json.AddItem(SerializeDateTime(dt)); }
  1110. else if (value is byte[] bytes) { json.AddItem(SerializeBytes(bytes)); }
  1111. else if (value is bool) { json.AddItem((bool)value); }
  1112. else if (value is byte) { json.AddItem((byte)value); }
  1113. else if (value is sbyte) { json.AddItem((sbyte)value); }
  1114. else if (value is short) { json.AddItem((short)value); }
  1115. else if (value is ushort) { json.AddItem((ushort)value); }
  1116. else if (value is int) { json.AddItem((int)value); }
  1117. else if (value is uint) { json.AddItem((uint)value); }
  1118. else if (value is long) { json.AddItem((long)value); }
  1119. else if (value is ulong) { json.AddItem(value.ToString()); }
  1120. else if (value is float) { json.AddItem((float)value); }
  1121. else if (value is double) { json.AddItem((double)value); }
  1122. else if (value is decimal) { json.AddItem((decimal)value); }
  1123. else if (value is string) { json.AddItem((string)value); }
  1124. else if (value is Json) { json.AddItem(value as Json); }
  1125. else
  1126. {
  1127. if ((depth < 0) || (0 < depth && previous.Length < depth))
  1128. {
  1129. var recursive = new ArrayBuilder<object>(16);
  1130. recursive.Add(previous);
  1131. recursive.Add(value);
  1132. if (value is IDictionary<string, object> asExpando)
  1133. {
  1134. var expando = new Dictionary<string, object>(asExpando);
  1135. json.AddItem(From(expando, lower, recursive, depth, force));
  1136. }
  1137. else if (value is IDictionary) { json.AddItem(From(value as IDictionary, lower, recursive, depth, force)); }
  1138. else if (value is IList) { json.AddItem(From(value as IList, lower, recursive, depth, force)); }
  1139. else { json.AddItem(From(value, lower, recursive, depth, force)); }
  1140. }
  1141. else
  1142. {
  1143. json.AddItem(value.ToString());
  1144. }
  1145. }
  1146. }
  1147. }
  1148. catch { }
  1149. return json;
  1150. }
  1151. private static Json From(IDictionary dictionary, bool lower, object[] previous, int depth, bool force)
  1152. {
  1153. if (dictionary == null) return null;
  1154. if (dictionary is IToJson) return ((IToJson)dictionary).ToJson();
  1155. // IDictionary 不再需要 SerializableAttribute 特性。
  1156. // {
  1157. // var dtype = dictionary.GetType();
  1158. // var sas = dtype.GetCustomAttributes(typeof(SerializableAttribute), false);
  1159. // if (sas == null || sas.Length < 1) return null;
  1160. // }
  1161. var checker = dictionary as IToJsonChecker;
  1162. var json = NewObject();
  1163. try
  1164. {
  1165. var keys = dictionary.Keys;
  1166. foreach (var key in keys)
  1167. {
  1168. if (key == null) continue;
  1169. try
  1170. {
  1171. var field = key.ToString() ?? "";
  1172. if (lower && !string.IsNullOrEmpty(field)) field = field.ToLower();
  1173. var value = dictionary[key];
  1174. // 检查递归引用。
  1175. var recursively = false;
  1176. foreach (var r in previous)
  1177. {
  1178. if (ReferenceEquals(r, value))
  1179. {
  1180. if (AllowRecursively) json.SetProperty(field);
  1181. recursively = true;
  1182. break;
  1183. }
  1184. }
  1185. if (recursively) continue;
  1186. // 检查 System.Attribute.TypeId。
  1187. if (field == "TypeId" || field == "typeid")
  1188. {
  1189. if ((value != null) && (value is Type))
  1190. {
  1191. json.SetProperty(field, FullName((Type)value));
  1192. continue;
  1193. }
  1194. }
  1195. // 由 IToJsonChecker 实现的方法检查是否包含元素。
  1196. if (checker != null && !checker.WithPropertyInJson(dictionary, field, value)) continue;
  1197. if (value != null)
  1198. {
  1199. // 处理 Type 对象。
  1200. if (value.GetType().Equals(typeof(Type)) && (previous.Length > 2))
  1201. {
  1202. value = FullName((Type)value);
  1203. }
  1204. // 处理 Assembly 对象。
  1205. if (value.GetType().Equals(typeof(Assembly)) && (previous.Length > 2))
  1206. {
  1207. value = ((Assembly)value).FullName;
  1208. }
  1209. }
  1210. if (value == null) { json.SetProperty(field); }
  1211. else if (value is DateTime dt) { json.SetProperty(field, SerializeDateTime(dt)); }
  1212. else if (value is byte[] bytes) { json.SetProperty(field, SerializeBytes(bytes)); }
  1213. else if (value is bool) { json.SetProperty(field, (bool)value); }
  1214. else if (value is byte) { json.SetProperty(field, (byte)value); }
  1215. else if (value is sbyte) { json.SetProperty(field, (sbyte)value); }
  1216. else if (value is short) { json.SetProperty(field, (short)value); }
  1217. else if (value is ushort) { json.SetProperty(field, (ushort)value); }
  1218. else if (value is int) { json.SetProperty(field, (int)value); }
  1219. else if (value is uint) { json.SetProperty(field, (uint)value); }
  1220. else if (value is long) { json.SetProperty(field, (long)value); }
  1221. else if (value is ulong) { json.SetProperty(field, value.ToString()); }
  1222. else if (value is float) { json.SetProperty(field, (float)value); }
  1223. else if (value is double) { json.SetProperty(field, (double)value); }
  1224. else if (value is decimal) { json.SetProperty(field, (decimal)value); }
  1225. else if (value is string) { json.SetProperty(field, (string)value); }
  1226. else if (value is Json) { json.SetProperty(field, value as Json); }
  1227. else
  1228. {
  1229. if ((depth < 0) || (0 < depth && previous.Length < depth))
  1230. {
  1231. var recursive = new ArrayBuilder<object>(16);
  1232. recursive.Add(previous);
  1233. recursive.Add(value);
  1234. if (value is IDictionary) { json.SetProperty(field, From(value as IDictionary, lower, recursive, depth, force)); }
  1235. else if (value is IList) { json.SetProperty(field, From(value as IList, lower, recursive, depth, force)); }
  1236. else { json.SetProperty(field, From(value, lower, recursive, depth, force)); }
  1237. }
  1238. else
  1239. {
  1240. json.SetProperty(field, value.ToString());
  1241. }
  1242. }
  1243. }
  1244. catch { }
  1245. }
  1246. }
  1247. catch { }
  1248. return json;
  1249. }
  1250. private static Json From(object entity, bool lower, object[] previous, int depth, bool force)
  1251. {
  1252. if (entity == null) return null;
  1253. if (entity is IToJson) return ((IToJson)entity).ToJson();
  1254. if (entity is string) return From(entity as string);
  1255. // 递归检查。
  1256. var pab = new ArrayBuilder<object>(16);
  1257. if (previous != null) pab.Add(previous as IEnumerable<object>);
  1258. pab.Add(entity);
  1259. var end = depth > 0 && pab.Count >= depth;
  1260. // 不可递归类型:类型。
  1261. if (entity is Type)
  1262. {
  1263. var t = entity as Type;
  1264. if (t.Equals(typeof(void))) return null;
  1265. var tJson = NewObject();
  1266. if (end) tJson.SetProperty(lower ? "name" : "Name", FullName(t));
  1267. else
  1268. {
  1269. tJson.SetProperty(lower ? "name" : "Name", t.Name);
  1270. if (t.IsGenericType)
  1271. {
  1272. tJson.SetProperty(lower ? "generic" : "Generic", From(t.GetGenericArguments(), lower, pab, 2, true));
  1273. }
  1274. tJson.SetProperty(lower ? "namespace" : "Namespace", t.Namespace);
  1275. }
  1276. tJson.SetProperty(lower ? "assembly" : "Assembly", t.Assembly.Location);
  1277. if (end)
  1278. {
  1279. tJson.SetProperty(lower ? "properties" : "Properties", t.GetProperties().Length);
  1280. tJson.SetProperty(lower ? "methods" : "Methods", t.GetMethods().Length);
  1281. }
  1282. else
  1283. {
  1284. tJson.SetProperty(lower ? "properties" : "Properties", From(t.GetProperties(), lower, new object[0], 1, true));
  1285. tJson.SetProperty(lower ? "methods" : "Methods", From(t.GetMethods(), lower, new object[0], 1, true));
  1286. }
  1287. return tJson;
  1288. }
  1289. // 不可递归类型:方法。
  1290. if (entity is MethodBase)
  1291. {
  1292. var mb = entity as MethodBase;
  1293. var mbJson = NewObject();
  1294. mbJson.SetProperty(lower ? "name" : "Name", mb.Name);
  1295. mbJson.SetProperty(lower ? "declaring" : "Declaring", FullName(mb.DeclaringType));
  1296. if (mb.IsStatic) mbJson.SetProperty(lower ? "static" : "Static", mb.IsStatic);
  1297. if (mb is MethodInfo mi)
  1298. {
  1299. mbJson.SetProperty(lower ? "type" : "Type", FullName(mi.ReturnType));
  1300. }
  1301. mbJson.SetProperty(lower ? "parameters" : "Parameters", mb.GetParameters().Length);
  1302. return mbJson;
  1303. }
  1304. // 不可递归类型:成员。
  1305. if (entity is MemberInfo)
  1306. {
  1307. var mi = entity as MemberInfo;
  1308. var miJson = NewObject();
  1309. miJson.SetProperty(lower ? "name" : "Name", mi.Name);
  1310. miJson.SetProperty(lower ? "declaring" : "Declaring", FullName(mi.DeclaringType));
  1311. miJson.SetProperty(lower ? "type" : "Type", mi.MemberType.ToString());
  1312. if (mi is PropertyInfo pi)
  1313. {
  1314. var getter = pi.GetGetMethod();
  1315. var setter = pi.GetSetMethod();
  1316. var isStatic = (getter != null && getter.IsStatic) || (setter != null && setter.IsStatic);
  1317. if (isStatic) miJson.SetProperty(lower ? "static" : "Static", isStatic);
  1318. miJson.SetProperty(lower ? "get" : "Get", getter != null);
  1319. miJson.SetProperty(lower ? "set" : "Set", setter != null);
  1320. }
  1321. else if (mi is FieldInfo fi)
  1322. {
  1323. if (fi.IsStatic) miJson.SetProperty(lower ? "static" : "Static", true);
  1324. }
  1325. return miJson;
  1326. }
  1327. // 不可递归类型:参数。
  1328. if (entity is ParameterInfo)
  1329. {
  1330. var pi = entity as ParameterInfo;
  1331. var piJson = NewObject();
  1332. piJson.SetProperty(lower ? "name" : "Name", pi.Name);
  1333. piJson.SetProperty(lower ? "type" : "Type", FullName(pi.ParameterType));
  1334. return piJson;
  1335. }
  1336. // 强制序列化。
  1337. var exception = entity as Exception;
  1338. if (exception != null) force = true;
  1339. if (!(force || _forceall) && !CanSerialize(entity.GetType(), false)) return null;
  1340. if (entity is Json) { if (lower) Lower(entity as Json); return entity as Json; }
  1341. else if (entity is String) { return From((string)entity); }
  1342. else if (entity is IDictionary<string, object> asExpando) { return From(new Dictionary<string, object>(asExpando), lower, depth, force); }
  1343. else if (entity is IDictionary) { return From(entity as IDictionary, lower, depth, force); }
  1344. else if (entity is IList) { return From(entity as IList, lower, depth, force); }
  1345. else if (entity is NameValueCollection nc) { return From(CollectionUtility.Dictionary(nc), lower, depth, force); }
  1346. var type = entity.GetType();
  1347. var independent = RuntimeUtility.Contains<IndependentAttribute>(type);
  1348. var checker = entity as IToJsonChecker;
  1349. var properties = type.GetProperties();
  1350. if (properties.LongLength > 0L)
  1351. {
  1352. var dict = new Dictionary<string, object>();
  1353. // 添加异常类型,并提前加入基类属性。
  1354. if (exception != null)
  1355. {
  1356. dict.Add(lower ? "type" : "Type", FullName(exception.GetType()));
  1357. dict.Add(lower ? "message" : "Message", Message(exception));
  1358. var exData = exception.Data;
  1359. if (exData != null && exData.Count > 0) dict.Add(lower ? "data" : "Data", exData);
  1360. var exHelpLink = exception.HelpLink;
  1361. if (!string.IsNullOrEmpty(exHelpLink)) dict.Add(lower ? "help" : "Help", exHelpLink);
  1362. if (!end)
  1363. {
  1364. var stackJson = NewArray();
  1365. var stackJsonLength = 0;
  1366. var stackText = exception.StackTrace;
  1367. if (!string.IsNullOrEmpty(stackText))
  1368. {
  1369. var stackSplit = exception.StackTrace.Split('\r', '\n');
  1370. foreach (var stackItem in stackSplit)
  1371. {
  1372. if (string.IsNullOrEmpty(stackItem)) continue;
  1373. var stackTrim = stackItem.Trim();
  1374. if (string.IsNullOrEmpty(stackTrim)) continue;
  1375. stackJson.AddItem(stackTrim);
  1376. stackJsonLength += 1;
  1377. }
  1378. }
  1379. if (stackJsonLength > 0) dict.Add(lower ? "stack" : "Stack", stackJson);
  1380. var exTargetSite = exception.TargetSite;
  1381. if (exTargetSite != null) dict.Add(lower ? "target" : "Target", From(exTargetSite, lower, pab, depth, true));
  1382. }
  1383. var innerEx = exception.InnerException;
  1384. if (innerEx != null)
  1385. {
  1386. if (end) dict.Add(lower ? "inner" : "InnerException", FullName(innerEx.GetType()));
  1387. else dict.Add(lower ? "inner" : "InnerException", From(innerEx, lower, pab, depth, true));
  1388. }
  1389. }
  1390. foreach (var property in properties)
  1391. {
  1392. var field = property.Name;
  1393. if (field == null) continue;
  1394. // 有 Independent 的对象不包含继承属性。
  1395. if (independent)
  1396. {
  1397. if (!property.DeclaringType.Equals(type)) continue;
  1398. }
  1399. // 异常不包含基类中的属性。
  1400. if (exception != null)
  1401. {
  1402. if (property.DeclaringType.Equals(typeof(Exception))) continue;
  1403. }
  1404. // 处理 Assembly 对象的 DefinedTypes 和 ExportedTypes 属性。
  1405. if (entity is Assembly)
  1406. {
  1407. var assembly = entity as Assembly;
  1408. if (assembly != null)
  1409. {
  1410. if (field == "DefinedTypes" || field == "ExportedTypes")
  1411. {
  1412. continue;
  1413. }
  1414. }
  1415. }
  1416. var getter = property.GetGetMethod(false);
  1417. if (getter == null) continue;
  1418. if (getter.IsStatic) continue;
  1419. var value = null as object;
  1420. try
  1421. {
  1422. value = getter.Invoke((object)entity, null);
  1423. // 由 IToJsonChecker 实现的方法检查是否包含元素。
  1424. if (checker != null && !checker.WithPropertyInJson(entity, property, value)) continue;
  1425. // 处理 Type 对象。
  1426. if (getter.ReturnType.Equals(typeof(Type)) && (previous.Length > 2))
  1427. {
  1428. value = FullName((Type)value);
  1429. }
  1430. // 处理 Assembly 对象。
  1431. if (getter.ReturnType.Equals(typeof(Assembly)) && (previous.Length > 2))
  1432. {
  1433. value = ((Assembly)value).FullName;
  1434. }
  1435. }
  1436. catch (Exception ex)
  1437. {
  1438. value = ex.Message;
  1439. }
  1440. if (!dict.ContainsKey(field)) dict.Add(field, value);
  1441. }
  1442. var json = From(dict, lower, previous, depth, force);
  1443. return json;
  1444. }
  1445. else
  1446. {
  1447. return NewObject();
  1448. }
  1449. }
  1450. private static void ToJson(Json parent, Array array, int rank, int[] indices)
  1451. {
  1452. var dimension = indices.Length;
  1453. var subIndices = new int[dimension + 1];
  1454. if (dimension > 0) indices.CopyTo(subIndices, 0);
  1455. var subLength = array.GetLength(dimension);
  1456. var end = dimension + 1 >= rank;
  1457. if (end)
  1458. {
  1459. var subLinear = new object[subLength];
  1460. for (var i = 0; i < subLength; i++)
  1461. {
  1462. subIndices[dimension] = i;
  1463. subLinear[i] = array.GetValue(subIndices);
  1464. }
  1465. var subJson = Json.From(subLinear);
  1466. parent.Reset(subJson);
  1467. }
  1468. else
  1469. {
  1470. for (var i = 0; i < subLength; i++)
  1471. {
  1472. subIndices[dimension] = i;
  1473. var subJson = Json.NewArray();
  1474. ToJson(subJson, array, rank, subIndices);
  1475. parent.AddItem(subJson);
  1476. }
  1477. }
  1478. }
  1479. #endregion
  1480. #region Json -> String
  1481. /// <summary>导出文本,可指定缩进。若类型为 String,则导出 String 值,忽略缩进。</summary>
  1482. internal static string Export(Json json, bool indented)
  1483. {
  1484. if (json == null) return "";
  1485. if (json._jtoken == null) return "";
  1486. if (json.TokenType == JTokenType.String && json._jvalue != null)
  1487. {
  1488. return json._jvalue.Value.ToString();
  1489. }
  1490. return json._jtoken.ToString(indented ? Formatting.Indented : Formatting.None);
  1491. }
  1492. /// <summary>生成字符串,默认不缩进。若类型为 String,则导出 String 值。</summary>
  1493. public override string ToString() => Export(this, false);
  1494. /// <summary>生成字符串,可指定缩进。若类型为 String,则导出 String 值,忽略缩进。</summary>
  1495. public string ToString(bool indented) => Export(this, indented);
  1496. #endregion
  1497. #region Json -> Object
  1498. /// <summary>填充类型实例,失败时返回 NULL 值。</summary>
  1499. internal static T Object<T>(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false) where T : class, new()
  1500. {
  1501. if (json == null) return null;
  1502. if (json._jtoken == null) return null;
  1503. if (json.TokenType != JTokenType.Object) return null;
  1504. var entity = Object(typeof(T), json, ignoreCase, ignoreCharacters, force);
  1505. return entity == null ? default : (T)entity;
  1506. }
  1507. /// <summary>将 Json 填充到数组列表,失败时返回 NULL 值。</summary>
  1508. internal static TItem[] Array<TItem>(Json json, bool ignoreCase = true, string ignoreCharacters = null, bool force = false)
  1509. {
  1510. if (json == null) return null;
  1511. if (json._jtoken == null) return null;
  1512. if (json.TokenType != JTokenType.Array) return null;
  1513. var instance = Array(typeof(TItem), json, ignoreCase, ignoreCharacters, force);
  1514. var array = (TItem[])instance;
  1515. return array;
  1516. }
  1517. static ConstructorInfo GetDeserializeConstructor(Type type)
  1518. {
  1519. var types = new Type[] { typeof(Json) };
  1520. var independent = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null);
  1521. if (independent == null) independent = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
  1522. return independent;
  1523. }
  1524. /// <summary>创建指定类型的新实例,将 Json 的内容填充到新实例中。</summary>
  1525. public static object Object(Type type, Json json, bool ignoreCase, string ignoreCharacters, bool force)
  1526. {
  1527. // 检查参数。
  1528. if (type == null) throw new ArgumentNullException(nameof(type));
  1529. if (json == null || json._jtoken == null) return null;
  1530. // 类型自己实现反序列化。
  1531. var independent = GetDeserializeConstructor(type);
  1532. if (independent != null) return independent.Invoke(new object[] { json });
  1533. // 是数组。
  1534. if (type.IsArray)
  1535. {
  1536. var itemType = GetTypeOfArrayItem(type);
  1537. return Array(itemType, json, ignoreCase, ignoreCharacters, force);
  1538. }
  1539. // 是列表
  1540. if (typeof(IList).IsAssignableFrom(type))
  1541. {
  1542. var genericTypes = type.GetGenericArguments();
  1543. if (genericTypes != null && genericTypes.Length == 1)
  1544. {
  1545. var genericType = genericTypes[0];
  1546. if (genericType != null)
  1547. {
  1548. var array = Array(genericType, json, ignoreCase, ignoreCharacters, force);
  1549. var list = ArrayToList(array, type);
  1550. return list;
  1551. }
  1552. }
  1553. }
  1554. // 必须是有效的 Json 实例。
  1555. if (json.TokenType != JTokenType.Object && json.TokenType != JTokenType.Array) return null;
  1556. // 必须有无参数的构造函数。
  1557. var constructor = type.GetConstructor(System.Type.EmptyTypes);
  1558. if (constructor == null) return null;
  1559. // 创建实例。
  1560. var entity = constructor.Invoke(null);
  1561. var jps = json.GetProperties();
  1562. if (jps.Length < 1) return entity;
  1563. var etype = entity.GetType();
  1564. var eps = etype.GetProperties();
  1565. if (eps.Length < 1) return entity;
  1566. foreach (var ep in eps)
  1567. {
  1568. foreach (var jp in jps)
  1569. {
  1570. var jpn = TextUtility.Trim(jp.Name);
  1571. var epn = TextUtility.Trim(ep.Name);
  1572. if (ignoreCharacters != null)
  1573. {
  1574. var characters = ignoreCharacters.ToCharArray();
  1575. foreach (var character in characters)
  1576. {
  1577. jpn.Replace(character.ToString(), "");
  1578. epn.Replace(character.ToString(), "");
  1579. }
  1580. }
  1581. if (ignoreCase)
  1582. {
  1583. if (jpn.Length > 0) jpn = jpn.ToLower();
  1584. if (epn.Length > 0) epn = epn.ToLower();
  1585. }
  1586. if (jpn.Length < 1 || epn.Length < 1) continue;
  1587. if (jpn != epn) continue;
  1588. var value = jp.Value;
  1589. if (value == null) continue;
  1590. Property(entity, ep, value, ignoreCase, ignoreCharacters, force);
  1591. }
  1592. }
  1593. return entity;
  1594. }
  1595. static void Add(object entity, object item, int index)
  1596. {
  1597. try
  1598. {
  1599. if (entity is Array array) array.SetValue(item, index);
  1600. else if (entity is IList list) list.Add(item);
  1601. }
  1602. catch (Exception ex)
  1603. {
  1604. if (_throw) throw ex;
  1605. }
  1606. }
  1607. /// <exception cref="ArgumentNullException" />
  1608. internal static object Array(Type itemType, Json json, bool ignoreCase, string ignoreCharacters, bool force)
  1609. {
  1610. if (itemType == null) throw new ArgumentNullException(nameof(itemType));
  1611. if (json == null) return null;
  1612. // 必须是有效的 Json 实例。
  1613. if (json.TokenType != JTokenType.Array) return null;
  1614. // 加入列表。
  1615. var items = json.GetItems();
  1616. var list = new List<object>(items.Length);
  1617. for (var index = 0; index < items.Length; index++)
  1618. {
  1619. var item = items[index];
  1620. if (item == null) list.Add(null);
  1621. else if (itemType.Equals(typeof(Json))) list.Add(item);
  1622. else if (itemType.Equals(typeof(string))) list.Add(item ? item.Text : null);
  1623. else if (itemType.Equals(typeof(byte))) list.Add(Byte(item.Text));
  1624. else if (itemType.Equals(typeof(short))) list.Add(Int16(item.Text));
  1625. else if (itemType.Equals(typeof(int))) list.Add(Int32(item.Text));
  1626. else if (itemType.Equals(typeof(long))) list.Add(Int64(item.Text));
  1627. else if (itemType.Equals(typeof(sbyte))) list.Add(SByte(item.Text));
  1628. else if (itemType.Equals(typeof(ushort))) list.Add(UInt16(item.Text));
  1629. else if (itemType.Equals(typeof(uint))) list.Add(UInt32(item.Text));
  1630. else if (itemType.Equals(typeof(ulong))) list.Add(UInt64(item.Text));
  1631. else if (itemType.Equals(typeof(float))) list.Add(Single(item.Text));
  1632. else if (itemType.Equals(typeof(double))) list.Add(Double(item.Text));
  1633. else if (itemType.Equals(typeof(decimal))) list.Add(Decimal(item.Text));
  1634. else
  1635. {
  1636. var serializable = (force || _forceall) ? true : CanSerialize(itemType, false);
  1637. if (serializable)
  1638. {
  1639. var itemInstance = Object(itemType, item, ignoreCase, ignoreCharacters, force);
  1640. list.Add(itemInstance);
  1641. }
  1642. else
  1643. {
  1644. list.Add(null);
  1645. }
  1646. }
  1647. }
  1648. // 输出数组。
  1649. var array = System.Array.CreateInstance(itemType, list.Count);
  1650. for (var i = 0; i < list.Count; i++) array.SetValue(list[i], i);
  1651. return array;
  1652. }
  1653. private static void Property(object entity, PropertyInfo property, object value, bool ignoreCase, string ignoreCharacters, bool force)
  1654. {
  1655. if (entity == null) return;
  1656. if (property == null) return;
  1657. if (value == null) return;
  1658. var setter = property.GetSetMethod();
  1659. if (setter == null) return;
  1660. var pt = property.PropertyType;
  1661. var ptname = FullName(property.PropertyType);
  1662. if (ptname == FullName(typeof(Json)))
  1663. {
  1664. if (value is Json) setter.Invoke(entity, new object[] { value });
  1665. }
  1666. else
  1667. {
  1668. if (pt.Equals(typeof(DateTime)))
  1669. {
  1670. if (AllowException)
  1671. {
  1672. setter.Invoke(entity, new object[] { DeserializeDateTime(value) });
  1673. }
  1674. else
  1675. {
  1676. try
  1677. {
  1678. setter.Invoke(entity, new object[] { DeserializeDateTime(value) });
  1679. }
  1680. catch { }
  1681. }
  1682. }
  1683. else if (pt.Equals(typeof(string)))
  1684. {
  1685. if (value is Json asJson) setter.Invoke(entity, new object[] { ((Json)value).TokenType == JTokenType.Null ? null : ((Json)value).Text });
  1686. else setter.Invoke(entity, new object[] { value.ToString() });
  1687. }
  1688. else if (pt.Equals(typeof(bool))) setter.Invoke(entity, new object[] { Boolean(value) });
  1689. else if (pt.Equals(typeof(byte))) setter.Invoke(entity, new object[] { Byte(value) });
  1690. else if (pt.Equals(typeof(sbyte))) setter.Invoke(entity, new object[] { SByte(value) });
  1691. else if (pt.Equals(typeof(short))) setter.Invoke(entity, new object[] { Int16(value) });
  1692. else if (pt.Equals(typeof(ushort))) setter.Invoke(entity, new object[] { UInt16(value) });
  1693. else if (pt.Equals(typeof(int))) setter.Invoke(entity, new object[] { Int32(value) });
  1694. else if (pt.Equals(typeof(uint))) setter.Invoke(entity, new object[] { UInt32(value) });
  1695. else if (pt.Equals(typeof(long))) setter.Invoke(entity, new object[] { Int64(value) });
  1696. else if (pt.Equals(typeof(ulong))) setter.Invoke(entity, new object[] { UInt64(value) });
  1697. else if (pt.Equals(typeof(float))) setter.Invoke(entity, new object[] { Float(value) });
  1698. else if (pt.Equals(typeof(double))) setter.Invoke(entity, new object[] { Double(value) });
  1699. else if (pt.Equals(typeof(decimal))) setter.Invoke(entity, new object[] { Decimal(value) });
  1700. else if (pt.Equals(typeof(byte[]))) setter.Invoke(entity, new object[] { DeserializeBytes(value) });
  1701. else
  1702. {
  1703. var serializable = (force || _forceall);
  1704. if (!serializable) serializable = CanSerialize(property.PropertyType, false);
  1705. if (serializable && value is Json json)
  1706. {
  1707. if (pt.IsArray)
  1708. {
  1709. var array = Array(pt.GetElementType(), json, ignoreCase, ignoreCharacters, force);
  1710. setter.Invoke(entity, array);
  1711. }
  1712. else if (typeof(IList).IsAssignableFrom(pt))
  1713. {
  1714. var genericTypes = pt.GetGenericArguments();
  1715. if (genericTypes != null && genericTypes.Length == 1)
  1716. {
  1717. var genericType = genericTypes[0];
  1718. if (genericType != null)
  1719. {
  1720. var array = Array(genericType, json, ignoreCase, ignoreCharacters, force);
  1721. var list = ArrayToList(array, pt);
  1722. setter.Invoke(entity, list);
  1723. }
  1724. }
  1725. }
  1726. else
  1727. {
  1728. var @object = Object(pt, json, ignoreCase, ignoreCharacters, force);
  1729. setter.Invoke(entity, @object);
  1730. }
  1731. }
  1732. }
  1733. }
  1734. }
  1735. static IList ArrayToList(object array, Type listType)
  1736. {
  1737. if (listType == null) throw new ArgumentNullException(nameof(listType));
  1738. if (array != null && array is Array a)
  1739. {
  1740. var list = Activator.CreateInstance(listType) as IList;
  1741. for (var i = 0; i < a.Length; i++) list.Add(a.GetValue(i));
  1742. return list;
  1743. }
  1744. return null;
  1745. }
  1746. #endregion
  1747. #endregion
  1748. #region Dynamic
  1749. #if !NET20
  1750. /// <summary></summary>
  1751. public override bool TryGetMember(GetMemberBinder binder, out object result)
  1752. {
  1753. if (!IsObject) throw new InvalidOperationException(IsNotJsonObject);
  1754. var contains = _jobject.ContainsKey(binder.Name);
  1755. if (!contains)
  1756. {
  1757. result = null;
  1758. return true;
  1759. }
  1760. var jtoken = _jobject.GetValue(binder.Name);
  1761. result = ParseJToken(jtoken);
  1762. return true;
  1763. }
  1764. /// <summary></summary>
  1765. public override bool TrySetMember(SetMemberBinder binder, object value)
  1766. {
  1767. if (!IsObject) throw new InvalidOperationException(IsNotJsonObject);
  1768. var contains = _jobject.ContainsKey(binder.Name);
  1769. if (contains)
  1770. {
  1771. _jobject[binder.Name] = ToJToken(value);
  1772. return true;
  1773. }
  1774. else
  1775. {
  1776. _jobject.Add(binder.Name, ToJToken(value));
  1777. return true;
  1778. }
  1779. }
  1780. private Class<T> DynamicIndex<T>(object[] indexes, Func<string, T> stringCallback, Func<int, T> intCallback)
  1781. {
  1782. var index = indexes[0];
  1783. if (index != null)
  1784. {
  1785. if (IsObject)
  1786. {
  1787. if (index is string name) return new Class<T>(stringCallback.Invoke(name));
  1788. }
  1789. if (IsArray)
  1790. {
  1791. if (index is int || index is short || index is byte || index is ushort || index is sbyte)
  1792. {
  1793. var int32 = int.Parse(index.ToString());
  1794. if (int32 < 0) throw new ArgumentOutOfRangeException("index", IndexLessZero);
  1795. return new Class<T>(intCallback(int32));
  1796. }
  1797. else if (index is long int64)
  1798. {
  1799. if (int64 < 0) throw new ArgumentOutOfRangeException("index", IndexLessZero);
  1800. if (int64 > int.MaxValue) throw new ArgumentOutOfRangeException("index", IndexGraterMax);
  1801. var int32 = Convert.ToInt32(int64);
  1802. return new Class<T>(intCallback(int32));
  1803. }
  1804. else if (index is uint uint32)
  1805. {
  1806. if (uint32 > int.MaxValue) throw new ArgumentOutOfRangeException("index", IndexGraterMax);
  1807. var int32 = Convert.ToInt32(uint32);
  1808. return new Class<T>(intCallback(int32));
  1809. }
  1810. else if (index is ulong uint64)
  1811. {
  1812. if (uint64 > int.MaxValue) throw new ArgumentOutOfRangeException("index", IndexGraterMax);
  1813. var int32 = Convert.ToInt32(uint64);
  1814. return new Class<T>(intCallback(int32));
  1815. }
  1816. }
  1817. }
  1818. throw new InvalidOperationException(InvalidIndex);
  1819. }
  1820. /// <summary></summary>
  1821. public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
  1822. {
  1823. var box = DynamicIndex(indexes, name =>
  1824. {
  1825. var property = GetProperty(name);
  1826. return ParseJToken(property?._jtoken);
  1827. }, index =>
  1828. {
  1829. return GetItem(index);
  1830. });
  1831. if (box == null)
  1832. {
  1833. result = null;
  1834. return false;
  1835. }
  1836. else
  1837. {
  1838. result = box.Value;
  1839. return true;
  1840. }
  1841. }
  1842. /// <summary></summary>
  1843. public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
  1844. {
  1845. var box = DynamicIndex(indexes, name =>
  1846. {
  1847. _jobject[name] = ToJToken(value);
  1848. return true;
  1849. }, index =>
  1850. {
  1851. SetItem(index, value);
  1852. return true;
  1853. });
  1854. return box != null;
  1855. }
  1856. /// <summary></summary>
  1857. public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
  1858. {
  1859. switch (binder.CallInfo.ArgumentNames.First().Lower())
  1860. {
  1861. case "tostring":
  1862. if (args == null)
  1863. {
  1864. result = ToString();
  1865. return true;
  1866. }
  1867. else
  1868. {
  1869. switch (args.Length)
  1870. {
  1871. case 0:
  1872. result = ToString();
  1873. return true;
  1874. case 1:
  1875. if (args[0] == null)
  1876. {
  1877. result = null;
  1878. return false;
  1879. }
  1880. else
  1881. {
  1882. if (args[0] is bool indented)
  1883. {
  1884. result = ToString(indented);
  1885. return true;
  1886. }
  1887. else if (args[0] is byte int8)
  1888. {
  1889. result = ToString(int8 == 1);
  1890. return true;
  1891. }
  1892. else if (args[0] is short int16)
  1893. {
  1894. result = ToString(int16 == 1);
  1895. return true;
  1896. }
  1897. else if (args[0] is int int32)
  1898. {
  1899. result = ToString(int32 == 1);
  1900. return true;
  1901. }
  1902. else if (args[0] is long int64)
  1903. {
  1904. result = ToString(int64 == 1);
  1905. return true;
  1906. }
  1907. else
  1908. {
  1909. result = null;
  1910. return false;
  1911. }
  1912. }
  1913. default:
  1914. result = null;
  1915. return false;
  1916. }
  1917. }
  1918. default:
  1919. result = null;
  1920. return false;
  1921. }
  1922. }
  1923. /// <summary></summary>
  1924. public override bool TryConvert(ConvertBinder binder, out object result)
  1925. {
  1926. if (binder.Type.Equals(typeof(Json)))
  1927. {
  1928. result = this;
  1929. return true;
  1930. }
  1931. if (binder.Type.Equals(typeof(string)))
  1932. {
  1933. result = ToString();
  1934. return true;
  1935. }
  1936. result = null;
  1937. return false;
  1938. }
  1939. #endif
  1940. #endregion
  1941. #region 运算符。
  1942. /// <summary>从 Json 到 Boolean 的隐式转换,判断 Json 对象可用。</summary>
  1943. public static implicit operator bool(Json json) => json != null && json.Available;
  1944. /// <summary>从 Json 到 String 的隐式转换,默认不缩进。</summary>
  1945. public static implicit operator string(Json json) => Export(json, false);
  1946. /// <summary>从 String 到 Json 的隐式转换。</summary>
  1947. /// <exception cref="System.Exception"></exception>
  1948. public static implicit operator Json(string text) => From(text);
  1949. #endregion
  1950. #region Statics
  1951. #region 创建实例。
  1952. /// <summary>创建新对象。</summary>
  1953. public static Json NewObject()
  1954. {
  1955. return new Json(new JObject());
  1956. }
  1957. /// <summary>创建新对象。</summary>
  1958. public static Json NewObject(Dictionary<string, string> dictionary)
  1959. {
  1960. var json = new Json(null);
  1961. json.Reset(dictionary);
  1962. return json;
  1963. }
  1964. /// <summary>创建新对象。</summary>
  1965. public static Json NewObject(TextSet dictionary)
  1966. {
  1967. var json = new Json(null);
  1968. json.Reset(dictionary);
  1969. return json;
  1970. }
  1971. /// <summary>创建新对象。</summary>
  1972. public static Json NewObject(ObjectSet<string> dictionary)
  1973. {
  1974. var json = new Json(null);
  1975. json.Reset(dictionary);
  1976. return json;
  1977. }
  1978. /// <summary>创建新对象。</summary>
  1979. public static Json NewArray()
  1980. {
  1981. return new Json(new JArray());
  1982. }
  1983. /// <summary>新建类型为 Property 的实例,值为 Null,失败时返回 Null。</summary>
  1984. /// <param name="name">Property 名称,不可为 Null。</param>
  1985. /// <exception cref="System.ArgumentNullException"></exception>
  1986. public static Json NewProperty(string name)
  1987. {
  1988. if (name == null)
  1989. {
  1990. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  1991. return null;
  1992. }
  1993. return new Json(new JProperty(name, null));
  1994. }
  1995. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  1996. /// <param name="name">Property 名称,不可为 Null。</param>
  1997. /// <param name="value">Property 值。</param>
  1998. /// <exception cref="System.ArgumentNullException"></exception>
  1999. public static Json NewProperty(string name, string value)
  2000. {
  2001. if (name == null)
  2002. {
  2003. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2004. return null;
  2005. }
  2006. return new Json(new JProperty(name, value));
  2007. }
  2008. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2009. /// <param name="name">Property 名称,不可为 Null。</param>
  2010. /// <param name="value">Property 值。</param>
  2011. /// <exception cref="System.ArgumentNullException"></exception>
  2012. public static Json NewProperty(string name, bool value)
  2013. {
  2014. if (name == null)
  2015. {
  2016. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2017. return null;
  2018. }
  2019. return new Json(new JProperty(name, value));
  2020. }
  2021. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2022. /// <param name="name">Property 名称,不可为 Null。</param>
  2023. /// <param name="value">Property 值。</param>
  2024. /// <exception cref="System.ArgumentNullException"></exception>
  2025. public static Json NewProperty(string name, int value)
  2026. {
  2027. if (name == null)
  2028. {
  2029. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2030. return null;
  2031. }
  2032. return new Json(new JProperty(name, value));
  2033. }
  2034. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2035. /// <param name="name">Property 名称,不可为 Null。</param>
  2036. /// <param name="value">Property 值。</param>
  2037. /// <exception cref="System.ArgumentNullException"></exception>
  2038. public static Json NewProperty(string name, long value)
  2039. {
  2040. if (name == null)
  2041. {
  2042. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2043. return null;
  2044. }
  2045. return new Json(new JProperty(name, value));
  2046. }
  2047. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2048. /// <param name="name">Property 名称,不可为 Null。</param>
  2049. /// <param name="value">Property 值。</param>
  2050. /// <exception cref="System.ArgumentNullException"></exception>
  2051. public static Json NewProperty(string name, float value)
  2052. {
  2053. if (name == null)
  2054. {
  2055. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2056. return null;
  2057. }
  2058. return new Json(new JProperty(name, value));
  2059. }
  2060. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2061. /// <param name="name">Property 名称,不可为 Null。</param>
  2062. /// <param name="value">Property 值。</param>
  2063. /// <exception cref="System.ArgumentNullException"></exception>
  2064. public static Json NewProperty(string name, double value)
  2065. {
  2066. if (name == null)
  2067. {
  2068. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2069. return null;
  2070. }
  2071. return new Json(new JProperty(name, value));
  2072. }
  2073. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2074. /// <param name="name">Property 名称,不可为 Null。</param>
  2075. /// <param name="value">Property 值。</param>
  2076. /// <exception cref="System.ArgumentNullException"></exception>
  2077. public static Json NewProperty(string name, decimal value)
  2078. {
  2079. if (name == null)
  2080. {
  2081. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2082. return null;
  2083. }
  2084. return new Json(new JProperty(name, value));
  2085. }
  2086. /// <summary>新建类型为 Property 的实例,失败时返回 Null。</summary>
  2087. /// <param name="name">Property 名称,不可为 Null。</param>
  2088. /// <param name="value">Property 值。</param>
  2089. /// <exception cref="System.ArgumentNullException"></exception>
  2090. public static Json NewProperty(string name, Json value)
  2091. {
  2092. if (name == null)
  2093. {
  2094. if (AllowException) throw new ArgumentNullException("name", "参数无效。");
  2095. return null;
  2096. }
  2097. if (value == null) return new Json(new JProperty(name, null));
  2098. return new Json(new JProperty(name, null));
  2099. }
  2100. #endregion
  2101. /// <summary>格式化 Json 文本。</summary>
  2102. public static string Format(string text)
  2103. {
  2104. if (text == null || text == "") return "";
  2105. try
  2106. {
  2107. var serializer = new Newtonsoft.Json.JsonSerializer();
  2108. var tr = (System.IO.TextReader)(new System.IO.StringReader(text));
  2109. var jtr = new Newtonsoft.Json.JsonTextReader(tr);
  2110. var obj = serializer.Deserialize(jtr);
  2111. if (obj != null)
  2112. {
  2113. var textWriter = new System.IO.StringWriter();
  2114. var jsonWriter = new Newtonsoft.Json.JsonTextWriter(textWriter)
  2115. {
  2116. Formatting = Newtonsoft.Json.Formatting.Indented,
  2117. Indentation = 4,
  2118. IndentChar = ' '
  2119. };
  2120. serializer.Serialize(jsonWriter, obj);
  2121. return textWriter.ToString();
  2122. }
  2123. else
  2124. {
  2125. return text;
  2126. }
  2127. }
  2128. catch
  2129. {
  2130. return text ?? "";
  2131. }
  2132. }
  2133. /// <summary>重命名属性名称。</summary>
  2134. public static Json Rename(Json json, Func<string, string> renamer)
  2135. {
  2136. if (json == null) return null;
  2137. switch (json.TokenType)
  2138. {
  2139. case JTokenType.Array:
  2140. var items = json.GetItems();
  2141. foreach (var i in items) Rename(i, renamer);
  2142. break;
  2143. case JTokenType.Object:
  2144. var properties = json.GetProperties();
  2145. foreach (var i in properties)
  2146. {
  2147. var name = i._jproperty.Name;
  2148. var value = i._jproperty.Value;
  2149. if (!string.IsNullOrEmpty(name))
  2150. {
  2151. var newName = renamer(name);
  2152. var newValue = Rename(new Json(value), renamer)?._jtoken;
  2153. if (name != newName)
  2154. {
  2155. i.Remove();
  2156. json._jobject.Add(newName, newValue ?? value);
  2157. }
  2158. }
  2159. }
  2160. break;
  2161. }
  2162. return json;
  2163. }
  2164. /// <summary>设置属性名称为小写。</summary>
  2165. public static Json Lower(Json json) => Rename(json, (old) => old.Lower());
  2166. /// <summary>设置属性名称为驼峰形式。</summary>
  2167. public static Json Camel(Json json) => Rename(json, (old) => TextUtility.Camel(old));
  2168. private static bool CanSerialize(Type type, bool inherit = false)
  2169. {
  2170. if (type == null) return false;
  2171. if (type.BaseType.Equals(typeof(Array))) return true;
  2172. var interfaces = type.GetInterfaces();
  2173. foreach (var i in interfaces)
  2174. {
  2175. if (i.Equals(typeof(IList))) return true;
  2176. }
  2177. if (type.Equals(typeof(object))) return false;
  2178. var sas = type.GetCustomAttributes(typeof(SerializableAttribute), inherit);
  2179. if (sas != null && sas.Length > 0) return true;
  2180. var tas = type.GetCustomAttributes(typeof(Source.TableAttribute), inherit);
  2181. if (tas != null && tas.Length > 0) return true;
  2182. return false;
  2183. }
  2184. /// <summary>序列化指定对象为 JSON 字符串。</summary>
  2185. /// <exception cref="Exception"></exception>
  2186. public static string SerializeObject(object @object, Type type = null, bool indented = false, string onError = null) => JsonConvert.SerializeObject(@object, type, indented ? Formatting.Indented : Formatting.None, null);
  2187. /// <summary>反序列化 JSON 字符串为指定的类型。</summary>
  2188. /// <exception cref="Exception"></exception>
  2189. public static T DeserializeObject<T>(string json) => (T)DeserializeObject(json, typeof(T));
  2190. /// <summary>反序列化 JSON 字符串为指定的类型。</summary>
  2191. /// <exception cref="Exception"></exception>
  2192. public static object DeserializeObject(string json, Type type = null) => JsonConvert.DeserializeObject(json, type, (JsonSerializerSettings)null);
  2193. #if !NET20
  2194. /// <summary>反序列化 JSON 字符串为指定的类型列表。</summary>
  2195. /// <typeparam name="T">要反序列化的类型。</typeparam>
  2196. /// <param name="json">将要反序列化的 JSON 字符串。</param>
  2197. /// <param name="returnNullOnError">发生错误时返回 NULL 值,设置为 FALSE 时返回空 List&lt;<typeparamref name="T"/>&gt; 对象。</param>
  2198. /// <returns></returns>
  2199. public static T[] DeserializeArray<T>(string json, bool returnNullOnError = false) where T : class
  2200. {
  2201. try
  2202. {
  2203. var serializer = new JsonSerializer();
  2204. var @object = null as object;
  2205. using (var sr = new StringReader(json))
  2206. {
  2207. using (var jtr = new JsonTextReader(sr))
  2208. {
  2209. @object = serializer.Deserialize(jtr, typeof(T[]));
  2210. }
  2211. }
  2212. return (@object as T[]) ?? new T[0];
  2213. }
  2214. catch { return returnNullOnError ? null : new T[0]; }
  2215. }
  2216. #endif
  2217. #endregion
  2218. #region Byte[]
  2219. static Func<byte[], string> _bytes_serializer = null;
  2220. static Func<object, byte[]> _bytes_deserializer = null;
  2221. /// <summary>自定义 Byte[] 序列化程序。</summary>
  2222. public static Func<byte[], string> BytesSerializer { get => _bytes_serializer; set => _bytes_serializer = value; }
  2223. /// <summary>自定义 Byte[] 反序列化程序。</summary>
  2224. public static Func<object, byte[]> BytesDeserializer { get => _bytes_deserializer; set => _bytes_deserializer = value; }
  2225. /// <summary>序列化 Byte[] 实例。</summary>
  2226. public static string SerializeBytes(byte[] bytes)
  2227. {
  2228. var serializer = _bytes_serializer;
  2229. if (serializer != null) return serializer.Invoke(bytes);
  2230. if (bytes == null) return null;
  2231. return Convert.ToBase64String(bytes);
  2232. }
  2233. /// <summary>反序列化 Byte[] 实例。</summary>
  2234. public static byte[] DeserializeBytes(object value)
  2235. {
  2236. var deserializer = _bytes_deserializer;
  2237. if (deserializer != null) return deserializer.Invoke(value);
  2238. try
  2239. {
  2240. if (value is byte[] bytes) return bytes;
  2241. if (value is string base64) return Convert.FromBase64String(base64);
  2242. return null;
  2243. }
  2244. catch
  2245. {
  2246. return null;
  2247. }
  2248. }
  2249. #endregion
  2250. #region DateTime
  2251. static Func<DateTime, string> _datetime_serializer = null;
  2252. static Func<object, DateTime> _datetime_deserializer = null;
  2253. /// <summary>自定义 DateTime 序列化程序。</summary>
  2254. public static Func<DateTime, string> DateTimeSerializer { get => _datetime_serializer; set => _datetime_serializer = value; }
  2255. /// <summary>自定义 DateTime 反序列化程序。</summary>
  2256. public static Func<object, DateTime> DateTimeDeserializer { get => _datetime_deserializer; set => _datetime_deserializer = value; }
  2257. /// <summary>序列化 DateTime 实例。</summary>
  2258. public static string SerializeDateTime(DateTime dateTime)
  2259. {
  2260. var serializer = _datetime_serializer;
  2261. if (serializer != null) return serializer.Invoke(dateTime);
  2262. return ClockUtility.Lucid(dateTime);
  2263. }
  2264. /// <summary>反序列化 DateTime 实例。</summary>
  2265. public static DateTime DeserializeDateTime(object value)
  2266. {
  2267. var deserializer = _datetime_deserializer;
  2268. if (deserializer != null) return deserializer.Invoke(value);
  2269. try
  2270. {
  2271. if (value is DateTime dt) return dt;
  2272. var text = value.ToString();
  2273. var parse = ClockUtility.Parse(text);
  2274. if (parse != null) return parse.Value;
  2275. }
  2276. catch { }
  2277. return default;
  2278. }
  2279. #endregion
  2280. }
  2281. }