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.

1015 lines
45 KiB

4 years ago
4 years ago
4 years ago
4 years ago
  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.IO;
  27. using System.Globalization;
  28. #if HAVE_BIG_INTEGER
  29. using System.Numerics;
  30. #endif
  31. using Newtonsoft.Json.Linq;
  32. using Newtonsoft.Json.Utilities;
  33. using System.Xml;
  34. using Newtonsoft.Json.Converters;
  35. using Newtonsoft.Json.Serialization;
  36. using System.Text;
  37. #if !NET20
  38. using System.Xml.Linq;
  39. #endif
  40. namespace Newtonsoft.Json
  41. {
  42. /// <summary>
  43. /// Provides methods for converting between .NET types and JSON types.
  44. /// </summary>
  45. /// <example>
  46. /// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="SerializeObject" title="Serializing and Deserializing JSON with JsonConvert" />
  47. /// </example>
  48. internal static class JsonConvert
  49. {
  50. /// <summary>
  51. /// Gets or sets a function that creates default <see cref="JsonSerializerSettings"/>.
  52. /// Default settings are automatically used by serialization methods on <see cref="JsonConvert"/>,
  53. /// and <see cref="JToken.ToObject{T}()"/> and <see cref="JToken.FromObject(object)"/> on <see cref="JToken"/>.
  54. /// To serialize without using any default settings create a <see cref="JsonSerializer"/> with
  55. /// <see cref="JsonSerializer.Create()"/>.
  56. /// </summary>
  57. public static Func<JsonSerializerSettings> DefaultSettings { get; set; }
  58. /// <summary>
  59. /// Represents JavaScript's boolean value <c>true</c> as a string. This field is read-only.
  60. /// </summary>
  61. public static readonly string True = "true";
  62. /// <summary>
  63. /// Represents JavaScript's boolean value <c>false</c> as a string. This field is read-only.
  64. /// </summary>
  65. public static readonly string False = "false";
  66. /// <summary>
  67. /// Represents JavaScript's <c>null</c> as a string. This field is read-only.
  68. /// </summary>
  69. public static readonly string Null = "null";
  70. /// <summary>
  71. /// Represents JavaScript's <c>undefined</c> as a string. This field is read-only.
  72. /// </summary>
  73. public static readonly string Undefined = "undefined";
  74. /// <summary>
  75. /// Represents JavaScript's positive infinity as a string. This field is read-only.
  76. /// </summary>
  77. public static readonly string PositiveInfinity = "Infinity";
  78. /// <summary>
  79. /// Represents JavaScript's negative infinity as a string. This field is read-only.
  80. /// </summary>
  81. public static readonly string NegativeInfinity = "-Infinity";
  82. /// <summary>
  83. /// Represents JavaScript's <c>NaN</c> as a string. This field is read-only.
  84. /// </summary>
  85. public static readonly string NaN = "NaN";
  86. /// <summary>
  87. /// Converts the <see cref="DateTime"/> to its JSON string representation.
  88. /// </summary>
  89. /// <param name="value">The value to convert.</param>
  90. /// <returns>A JSON string representation of the <see cref="DateTime"/>.</returns>
  91. public static string ToString(DateTime value)
  92. {
  93. return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
  94. }
  95. /// <summary>
  96. /// Converts the <see cref="DateTime"/> to its JSON string representation using the <see cref="DateFormatHandling"/> specified.
  97. /// </summary>
  98. /// <param name="value">The value to convert.</param>
  99. /// <param name="format">The format the date will be converted to.</param>
  100. /// <param name="timeZoneHandling">The time zone handling when the date is converted to a string.</param>
  101. /// <returns>A JSON string representation of the <see cref="DateTime"/>.</returns>
  102. public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
  103. {
  104. DateTime updatedDateTime = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
  105. using (StringWriter writer = StringUtils.CreateStringWriter(64))
  106. {
  107. writer.Write('"');
  108. DateTimeUtils.WriteDateTimeString(writer, updatedDateTime, format, null, CultureInfo.InvariantCulture);
  109. writer.Write('"');
  110. return writer.ToString();
  111. }
  112. }
  113. #if !NET20
  114. /// <summary>
  115. /// Converts the <see cref="DateTimeOffset"/> to its JSON string representation.
  116. /// </summary>
  117. /// <param name="value">The value to convert.</param>
  118. /// <returns>A JSON string representation of the <see cref="DateTimeOffset"/>.</returns>
  119. public static string ToString(DateTimeOffset value)
  120. {
  121. return ToString(value, DateFormatHandling.IsoDateFormat);
  122. }
  123. /// <summary>
  124. /// Converts the <see cref="DateTimeOffset"/> to its JSON string representation using the <see cref="DateFormatHandling"/> specified.
  125. /// </summary>
  126. /// <param name="value">The value to convert.</param>
  127. /// <param name="format">The format the date will be converted to.</param>
  128. /// <returns>A JSON string representation of the <see cref="DateTimeOffset"/>.</returns>
  129. public static string ToString(DateTimeOffset value, DateFormatHandling format)
  130. {
  131. using (StringWriter writer = StringUtils.CreateStringWriter(64))
  132. {
  133. writer.Write('"');
  134. DateTimeUtils.WriteDateTimeOffsetString(writer, value, format, null, CultureInfo.InvariantCulture);
  135. writer.Write('"');
  136. return writer.ToString();
  137. }
  138. }
  139. #endif
  140. /// <summary>
  141. /// Converts the <see cref="Boolean"/> to its JSON string representation.
  142. /// </summary>
  143. /// <param name="value">The value to convert.</param>
  144. /// <returns>A JSON string representation of the <see cref="Boolean"/>.</returns>
  145. public static string ToString(bool value)
  146. {
  147. return (value) ? True : False;
  148. }
  149. /// <summary>
  150. /// Converts the <see cref="Char"/> to its JSON string representation.
  151. /// </summary>
  152. /// <param name="value">The value to convert.</param>
  153. /// <returns>A JSON string representation of the <see cref="Char"/>.</returns>
  154. public static string ToString(char value)
  155. {
  156. return ToString(char.ToString(value));
  157. }
  158. /// <summary>
  159. /// Converts the <see cref="Enum"/> to its JSON string representation.
  160. /// </summary>
  161. /// <param name="value">The value to convert.</param>
  162. /// <returns>A JSON string representation of the <see cref="Enum"/>.</returns>
  163. public static string ToString(Enum value)
  164. {
  165. return value.ToString("D");
  166. }
  167. /// <summary>
  168. /// Converts the <see cref="Int32"/> to its JSON string representation.
  169. /// </summary>
  170. /// <param name="value">The value to convert.</param>
  171. /// <returns>A JSON string representation of the <see cref="Int32"/>.</returns>
  172. public static string ToString(int value)
  173. {
  174. return value.ToString(null, CultureInfo.InvariantCulture);
  175. }
  176. /// <summary>
  177. /// Converts the <see cref="Int16"/> to its JSON string representation.
  178. /// </summary>
  179. /// <param name="value">The value to convert.</param>
  180. /// <returns>A JSON string representation of the <see cref="Int16"/>.</returns>
  181. public static string ToString(short value)
  182. {
  183. return value.ToString(null, CultureInfo.InvariantCulture);
  184. }
  185. /// <summary>
  186. /// Converts the <see cref="UInt16"/> to its JSON string representation.
  187. /// </summary>
  188. /// <param name="value">The value to convert.</param>
  189. /// <returns>A JSON string representation of the <see cref="UInt16"/>.</returns>
  190. public static string ToString(ushort value)
  191. {
  192. return value.ToString(null, CultureInfo.InvariantCulture);
  193. }
  194. /// <summary>
  195. /// Converts the <see cref="UInt32"/> to its JSON string representation.
  196. /// </summary>
  197. /// <param name="value">The value to convert.</param>
  198. /// <returns>A JSON string representation of the <see cref="UInt32"/>.</returns>
  199. public static string ToString(uint value)
  200. {
  201. return value.ToString(null, CultureInfo.InvariantCulture);
  202. }
  203. /// <summary>
  204. /// Converts the <see cref="Int64"/> to its JSON string representation.
  205. /// </summary>
  206. /// <param name="value">The value to convert.</param>
  207. /// <returns>A JSON string representation of the <see cref="Int64"/>.</returns>
  208. public static string ToString(long value)
  209. {
  210. return value.ToString(null, CultureInfo.InvariantCulture);
  211. }
  212. #if HAVE_BIG_INTEGER
  213. private static string ToStringInternal(BigInteger value)
  214. {
  215. return value.ToString(null, CultureInfo.InvariantCulture);
  216. }
  217. #endif
  218. /// <summary>
  219. /// Converts the <see cref="UInt64"/> to its JSON string representation.
  220. /// </summary>
  221. /// <param name="value">The value to convert.</param>
  222. /// <returns>A JSON string representation of the <see cref="UInt64"/>.</returns>
  223. public static string ToString(ulong value)
  224. {
  225. return value.ToString(null, CultureInfo.InvariantCulture);
  226. }
  227. /// <summary>
  228. /// Converts the <see cref="Single"/> to its JSON string representation.
  229. /// </summary>
  230. /// <param name="value">The value to convert.</param>
  231. /// <returns>A JSON string representation of the <see cref="Single"/>.</returns>
  232. public static string ToString(float value)
  233. {
  234. return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
  235. }
  236. internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
  237. {
  238. return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
  239. }
  240. private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
  241. {
  242. if (floatFormatHandling == FloatFormatHandling.Symbol || !(double.IsInfinity(value) || double.IsNaN(value)))
  243. {
  244. return text;
  245. }
  246. if (floatFormatHandling == FloatFormatHandling.DefaultValue)
  247. {
  248. return (!nullable) ? "0.0" : Null;
  249. }
  250. return quoteChar + text + quoteChar;
  251. }
  252. /// <summary>
  253. /// Converts the <see cref="Double"/> to its JSON string representation.
  254. /// </summary>
  255. /// <param name="value">The value to convert.</param>
  256. /// <returns>A JSON string representation of the <see cref="Double"/>.</returns>
  257. public static string ToString(double value)
  258. {
  259. return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
  260. }
  261. internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
  262. {
  263. return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
  264. }
  265. private static string EnsureDecimalPlace(double value, string text)
  266. {
  267. if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1)
  268. {
  269. return text;
  270. }
  271. return text + ".0";
  272. }
  273. private static string EnsureDecimalPlace(string text)
  274. {
  275. if (text.IndexOf('.') != -1)
  276. {
  277. return text;
  278. }
  279. return text + ".0";
  280. }
  281. /// <summary>
  282. /// Converts the <see cref="Byte"/> to its JSON string representation.
  283. /// </summary>
  284. /// <param name="value">The value to convert.</param>
  285. /// <returns>A JSON string representation of the <see cref="Byte"/>.</returns>
  286. public static string ToString(byte value)
  287. {
  288. return value.ToString(null, CultureInfo.InvariantCulture);
  289. }
  290. /// <summary>
  291. /// Converts the <see cref="SByte"/> to its JSON string representation.
  292. /// </summary>
  293. /// <param name="value">The value to convert.</param>
  294. /// <returns>A JSON string representation of the <see cref="SByte"/>.</returns>
  295. public static string ToString(sbyte value)
  296. {
  297. return value.ToString(null, CultureInfo.InvariantCulture);
  298. }
  299. /// <summary>
  300. /// Converts the <see cref="Decimal"/> to its JSON string representation.
  301. /// </summary>
  302. /// <param name="value">The value to convert.</param>
  303. /// <returns>A JSON string representation of the <see cref="SByte"/>.</returns>
  304. public static string ToString(decimal value)
  305. {
  306. return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
  307. }
  308. /// <summary>
  309. /// Converts the <see cref="Guid"/> to its JSON string representation.
  310. /// </summary>
  311. /// <param name="value">The value to convert.</param>
  312. /// <returns>A JSON string representation of the <see cref="Guid"/>.</returns>
  313. public static string ToString(Guid value)
  314. {
  315. return ToString(value, '"');
  316. }
  317. internal static string ToString(Guid value, char quoteChar)
  318. {
  319. string text;
  320. string qc;
  321. #if HAVE_CHAR_TO_STRING_WITH_CULTURE
  322. text = value.ToString("D", CultureInfo.InvariantCulture);
  323. qc = quoteChar.ToString(CultureInfo.InvariantCulture);
  324. #else
  325. text = value.ToString("D");
  326. qc = quoteChar.ToString();
  327. #endif
  328. return qc + text + qc;
  329. }
  330. /// <summary>
  331. /// Converts the <see cref="TimeSpan"/> to its JSON string representation.
  332. /// </summary>
  333. /// <param name="value">The value to convert.</param>
  334. /// <returns>A JSON string representation of the <see cref="TimeSpan"/>.</returns>
  335. public static string ToString(TimeSpan value)
  336. {
  337. return ToString(value, '"');
  338. }
  339. internal static string ToString(TimeSpan value, char quoteChar)
  340. {
  341. return ToString(value.ToString(), quoteChar);
  342. }
  343. /// <summary>
  344. /// Converts the <see cref="Uri"/> to its JSON string representation.
  345. /// </summary>
  346. /// <param name="value">The value to convert.</param>
  347. /// <returns>A JSON string representation of the <see cref="Uri"/>.</returns>
  348. public static string ToString(Uri value)
  349. {
  350. if (value == null)
  351. {
  352. return Null;
  353. }
  354. return ToString(value, '"');
  355. }
  356. internal static string ToString(Uri value, char quoteChar)
  357. {
  358. return ToString(value.OriginalString, quoteChar);
  359. }
  360. /// <summary>
  361. /// Converts the <see cref="String"/> to its JSON string representation.
  362. /// </summary>
  363. /// <param name="value">The value to convert.</param>
  364. /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
  365. public static string ToString(string value)
  366. {
  367. return ToString(value, '"');
  368. }
  369. /// <summary>
  370. /// Converts the <see cref="String"/> to its JSON string representation.
  371. /// </summary>
  372. /// <param name="value">The value to convert.</param>
  373. /// <param name="delimiter">The string delimiter character.</param>
  374. /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
  375. public static string ToString(string value, char delimiter)
  376. {
  377. return ToString(value, delimiter, StringEscapeHandling.Default);
  378. }
  379. /// <summary>
  380. /// Converts the <see cref="String"/> to its JSON string representation.
  381. /// </summary>
  382. /// <param name="value">The value to convert.</param>
  383. /// <param name="delimiter">The string delimiter character.</param>
  384. /// <param name="stringEscapeHandling">The string escape handling.</param>
  385. /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
  386. public static string ToString(string value, char delimiter, StringEscapeHandling stringEscapeHandling)
  387. {
  388. if (delimiter != '"' && delimiter != '\'')
  389. {
  390. throw new ArgumentException("Delimiter must be a single or double quote.", nameof(delimiter));
  391. }
  392. return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, true, stringEscapeHandling);
  393. }
  394. /// <summary>
  395. /// Converts the <see cref="Object"/> to its JSON string representation.
  396. /// </summary>
  397. /// <param name="value">The value to convert.</param>
  398. /// <returns>A JSON string representation of the <see cref="Object"/>.</returns>
  399. public static string ToString(object value)
  400. {
  401. if (value == null)
  402. {
  403. return Null;
  404. }
  405. PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value.GetType());
  406. switch (typeCode)
  407. {
  408. case PrimitiveTypeCode.String:
  409. return ToString((string)value);
  410. case PrimitiveTypeCode.Char:
  411. return ToString((char)value);
  412. case PrimitiveTypeCode.Boolean:
  413. return ToString((bool)value);
  414. case PrimitiveTypeCode.SByte:
  415. return ToString((sbyte)value);
  416. case PrimitiveTypeCode.Int16:
  417. return ToString((short)value);
  418. case PrimitiveTypeCode.UInt16:
  419. return ToString((ushort)value);
  420. case PrimitiveTypeCode.Int32:
  421. return ToString((int)value);
  422. case PrimitiveTypeCode.Byte:
  423. return ToString((byte)value);
  424. case PrimitiveTypeCode.UInt32:
  425. return ToString((uint)value);
  426. case PrimitiveTypeCode.Int64:
  427. return ToString((long)value);
  428. case PrimitiveTypeCode.UInt64:
  429. return ToString((ulong)value);
  430. case PrimitiveTypeCode.Single:
  431. return ToString((float)value);
  432. case PrimitiveTypeCode.Double:
  433. return ToString((double)value);
  434. case PrimitiveTypeCode.DateTime:
  435. return ToString((DateTime)value);
  436. case PrimitiveTypeCode.Decimal:
  437. return ToString((decimal)value);
  438. case PrimitiveTypeCode.DBNull:
  439. return Null;
  440. #if !NET20
  441. case PrimitiveTypeCode.DateTimeOffset:
  442. return ToString((DateTimeOffset)value);
  443. #endif
  444. case PrimitiveTypeCode.Guid:
  445. return ToString((Guid)value);
  446. case PrimitiveTypeCode.Uri:
  447. return ToString((Uri)value);
  448. case PrimitiveTypeCode.TimeSpan:
  449. return ToString((TimeSpan)value);
  450. #if HAVE_BIG_INTEGER
  451. case PrimitiveTypeCode.BigInteger:
  452. return ToStringInternal((BigInteger)value);
  453. #endif
  454. }
  455. throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
  456. }
  457. #region Serialize
  458. /// <summary>
  459. /// Serializes the specified object to a JSON string.
  460. /// </summary>
  461. /// <param name="value">The object to serialize.</param>
  462. /// <returns>A JSON string representation of the object.</returns>
  463. public static string SerializeObject(object value)
  464. {
  465. return SerializeObject(value, null, (JsonSerializerSettings)null);
  466. }
  467. /// <summary>
  468. /// Serializes the specified object to a JSON string using formatting.
  469. /// </summary>
  470. /// <param name="value">The object to serialize.</param>
  471. /// <param name="formatting">Indicates how the output should be formatted.</param>
  472. /// <returns>
  473. /// A JSON string representation of the object.
  474. /// </returns>
  475. public static string SerializeObject(object value, Formatting formatting)
  476. {
  477. return SerializeObject(value, formatting, (JsonSerializerSettings)null);
  478. }
  479. /// <summary>
  480. /// Serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
  481. /// </summary>
  482. /// <param name="value">The object to serialize.</param>
  483. /// <param name="converters">A collection of converters used while serializing.</param>
  484. /// <returns>A JSON string representation of the object.</returns>
  485. public static string SerializeObject(object value, params JsonConverter[] converters)
  486. {
  487. JsonSerializerSettings settings = (converters != null && converters.Length > 0)
  488. ? new JsonSerializerSettings { Converters = converters }
  489. : null;
  490. return SerializeObject(value, null, settings);
  491. }
  492. /// <summary>
  493. /// Serializes the specified object to a JSON string using formatting and a collection of <see cref="JsonConverter"/>.
  494. /// </summary>
  495. /// <param name="value">The object to serialize.</param>
  496. /// <param name="formatting">Indicates how the output should be formatted.</param>
  497. /// <param name="converters">A collection of converters used while serializing.</param>
  498. /// <returns>A JSON string representation of the object.</returns>
  499. public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters)
  500. {
  501. JsonSerializerSettings settings = (converters != null && converters.Length > 0)
  502. ? new JsonSerializerSettings { Converters = converters }
  503. : null;
  504. return SerializeObject(value, null, formatting, settings);
  505. }
  506. /// <summary>
  507. /// Serializes the specified object to a JSON string using <see cref="JsonSerializerSettings"/>.
  508. /// </summary>
  509. /// <param name="value">The object to serialize.</param>
  510. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  511. /// If this is <c>null</c>, default serialization settings will be used.</param>
  512. /// <returns>
  513. /// A JSON string representation of the object.
  514. /// </returns>
  515. public static string SerializeObject(object value, JsonSerializerSettings settings)
  516. {
  517. return SerializeObject(value, null, settings);
  518. }
  519. /// <summary>
  520. /// Serializes the specified object to a JSON string using a type, formatting and <see cref="JsonSerializerSettings"/>.
  521. /// </summary>
  522. /// <param name="value">The object to serialize.</param>
  523. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  524. /// If this is <c>null</c>, default serialization settings will be used.</param>
  525. /// <param name="type">
  526. /// The type of the value being serialized.
  527. /// This parameter is used when <see cref="JsonSerializer.TypeNameHandling"/> is <see cref="TypeNameHandling.Auto"/> to write out the type name if the type of the value does not match.
  528. /// Specifying the type is optional.
  529. /// </param>
  530. /// <returns>
  531. /// A JSON string representation of the object.
  532. /// </returns>
  533. public static string SerializeObject(object value, Type type, JsonSerializerSettings settings)
  534. {
  535. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  536. return SerializeObjectInternal(value, type, jsonSerializer);
  537. }
  538. /// <summary>
  539. /// Serializes the specified object to a JSON string using formatting and <see cref="JsonSerializerSettings"/>.
  540. /// </summary>
  541. /// <param name="value">The object to serialize.</param>
  542. /// <param name="formatting">Indicates how the output should be formatted.</param>
  543. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  544. /// If this is <c>null</c>, default serialization settings will be used.</param>
  545. /// <returns>
  546. /// A JSON string representation of the object.
  547. /// </returns>
  548. public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings)
  549. {
  550. return SerializeObject(value, null, formatting, settings);
  551. }
  552. /// <summary>
  553. /// Serializes the specified object to a JSON string using a type, formatting and <see cref="JsonSerializerSettings"/>.
  554. /// </summary>
  555. /// <param name="value">The object to serialize.</param>
  556. /// <param name="formatting">Indicates how the output should be formatted.</param>
  557. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  558. /// If this is <c>null</c>, default serialization settings will be used.</param>
  559. /// <param name="type">
  560. /// The type of the value being serialized.
  561. /// This parameter is used when <see cref="JsonSerializer.TypeNameHandling"/> is <see cref="TypeNameHandling.Auto"/> to write out the type name if the type of the value does not match.
  562. /// Specifying the type is optional.
  563. /// </param>
  564. /// <returns>
  565. /// A JSON string representation of the object.
  566. /// </returns>
  567. public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings)
  568. {
  569. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  570. jsonSerializer.Formatting = formatting;
  571. return SerializeObjectInternal(value, type, jsonSerializer);
  572. }
  573. private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer)
  574. {
  575. StringBuilder sb = new StringBuilder(256);
  576. StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
  577. using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
  578. {
  579. jsonWriter.Formatting = jsonSerializer.Formatting;
  580. jsonSerializer.Serialize(jsonWriter, value, type);
  581. }
  582. return sw.ToString();
  583. }
  584. #endregion
  585. #region Deserialize
  586. /// <summary>
  587. /// Deserializes the JSON to a .NET object.
  588. /// </summary>
  589. /// <param name="value">The JSON to deserialize.</param>
  590. /// <returns>The deserialized object from the JSON string.</returns>
  591. public static object DeserializeObject(string value)
  592. {
  593. return DeserializeObject(value, null, (JsonSerializerSettings)null);
  594. }
  595. /// <summary>
  596. /// Deserializes the JSON to a .NET object using <see cref="JsonSerializerSettings"/>.
  597. /// </summary>
  598. /// <param name="value">The JSON to deserialize.</param>
  599. /// <param name="settings">
  600. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  601. /// If this is <c>null</c>, default serialization settings will be used.
  602. /// </param>
  603. /// <returns>The deserialized object from the JSON string.</returns>
  604. public static object DeserializeObject(string value, JsonSerializerSettings settings)
  605. {
  606. return DeserializeObject(value, null, settings);
  607. }
  608. /// <summary>
  609. /// Deserializes the JSON to the specified .NET type.
  610. /// </summary>
  611. /// <param name="value">The JSON to deserialize.</param>
  612. /// <param name="type">The <see cref="Type"/> of object being deserialized.</param>
  613. /// <returns>The deserialized object from the JSON string.</returns>
  614. public static object DeserializeObject(string value, Type type)
  615. {
  616. return DeserializeObject(value, type, (JsonSerializerSettings)null);
  617. }
  618. /// <summary>
  619. /// Deserializes the JSON to the specified .NET type.
  620. /// </summary>
  621. /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
  622. /// <param name="value">The JSON to deserialize.</param>
  623. /// <returns>The deserialized object from the JSON string.</returns>
  624. public static T DeserializeObject<T>(string value)
  625. {
  626. return DeserializeObject<T>(value, (JsonSerializerSettings)null);
  627. }
  628. /// <summary>
  629. /// Deserializes the JSON to the given anonymous type.
  630. /// </summary>
  631. /// <typeparam name="T">
  632. /// The anonymous type to deserialize to. This can't be specified
  633. /// traditionally and must be inferred from the anonymous type passed
  634. /// as a parameter.
  635. /// </typeparam>
  636. /// <param name="value">The JSON to deserialize.</param>
  637. /// <param name="anonymousTypeObject">The anonymous type object.</param>
  638. /// <returns>The deserialized anonymous type from the JSON string.</returns>
  639. public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
  640. {
  641. return DeserializeObject<T>(value);
  642. }
  643. /// <summary>
  644. /// Deserializes the JSON to the given anonymous type using <see cref="JsonSerializerSettings"/>.
  645. /// </summary>
  646. /// <typeparam name="T">
  647. /// The anonymous type to deserialize to. This can't be specified
  648. /// traditionally and must be inferred from the anonymous type passed
  649. /// as a parameter.
  650. /// </typeparam>
  651. /// <param name="value">The JSON to deserialize.</param>
  652. /// <param name="anonymousTypeObject">The anonymous type object.</param>
  653. /// <param name="settings">
  654. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  655. /// If this is <c>null</c>, default serialization settings will be used.
  656. /// </param>
  657. /// <returns>The deserialized anonymous type from the JSON string.</returns>
  658. public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
  659. {
  660. return DeserializeObject<T>(value, settings);
  661. }
  662. /// <summary>
  663. /// Deserializes the JSON to the specified .NET type using a collection of <see cref="JsonConverter"/>.
  664. /// </summary>
  665. /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
  666. /// <param name="value">The JSON to deserialize.</param>
  667. /// <param name="converters">Converters to use while deserializing.</param>
  668. /// <returns>The deserialized object from the JSON string.</returns>
  669. public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
  670. {
  671. return (T)DeserializeObject(value, typeof(T), converters);
  672. }
  673. /// <summary>
  674. /// Deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
  675. /// </summary>
  676. /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
  677. /// <param name="value">The object to deserialize.</param>
  678. /// <param name="settings">
  679. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  680. /// If this is <c>null</c>, default serialization settings will be used.
  681. /// </param>
  682. /// <returns>The deserialized object from the JSON string.</returns>
  683. public static T DeserializeObject<T>(string value, JsonSerializerSettings settings)
  684. {
  685. return (T)DeserializeObject(value, typeof(T), settings);
  686. }
  687. /// <summary>
  688. /// Deserializes the JSON to the specified .NET type using a collection of <see cref="JsonConverter"/>.
  689. /// </summary>
  690. /// <param name="value">The JSON to deserialize.</param>
  691. /// <param name="type">The type of the object to deserialize.</param>
  692. /// <param name="converters">Converters to use while deserializing.</param>
  693. /// <returns>The deserialized object from the JSON string.</returns>
  694. public static object DeserializeObject(string value, Type type, params JsonConverter[] converters)
  695. {
  696. JsonSerializerSettings settings = (converters != null && converters.Length > 0)
  697. ? new JsonSerializerSettings { Converters = converters }
  698. : null;
  699. return DeserializeObject(value, type, settings);
  700. }
  701. /// <summary>
  702. /// Deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
  703. /// </summary>
  704. /// <param name="value">The JSON to deserialize.</param>
  705. /// <param name="type">The type of the object to deserialize to.</param>
  706. /// <param name="settings">
  707. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  708. /// If this is <c>null</c>, default serialization settings will be used.
  709. /// </param>
  710. /// <returns>The deserialized object from the JSON string.</returns>
  711. public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings)
  712. {
  713. ValidationUtils.ArgumentNotNull(value, nameof(value));
  714. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  715. // by default DeserializeObject should check for additional content
  716. if (!jsonSerializer.IsCheckAdditionalContentSet())
  717. {
  718. jsonSerializer.CheckAdditionalContent = true;
  719. }
  720. using (JsonTextReader reader = new JsonTextReader(new StringReader(value)))
  721. {
  722. return jsonSerializer.Deserialize(reader, type);
  723. }
  724. }
  725. #endregion
  726. #region Populate
  727. /// <summary>
  728. /// Populates the object with values from the JSON string.
  729. /// </summary>
  730. /// <param name="value">The JSON to populate values from.</param>
  731. /// <param name="target">The target object to populate values onto.</param>
  732. public static void PopulateObject(string value, object target)
  733. {
  734. PopulateObject(value, target, null);
  735. }
  736. /// <summary>
  737. /// Populates the object with values from the JSON string using <see cref="JsonSerializerSettings"/>.
  738. /// </summary>
  739. /// <param name="value">The JSON to populate values from.</param>
  740. /// <param name="target">The target object to populate values onto.</param>
  741. /// <param name="settings">
  742. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  743. /// If this is <c>null</c>, default serialization settings will be used.
  744. /// </param>
  745. public static void PopulateObject(string value, object target, JsonSerializerSettings settings)
  746. {
  747. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  748. using (JsonReader jsonReader = new JsonTextReader(new StringReader(value)))
  749. {
  750. jsonSerializer.Populate(jsonReader, target);
  751. if (settings != null && settings.CheckAdditionalContent)
  752. {
  753. while (jsonReader.Read())
  754. {
  755. if (jsonReader.TokenType != JsonToken.Comment)
  756. {
  757. throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object.");
  758. }
  759. }
  760. }
  761. }
  762. }
  763. #endregion
  764. #region Xml
  765. /// <summary>
  766. /// Serializes the <see cref="XmlNode"/> to a JSON string.
  767. /// </summary>
  768. /// <param name="node">The node to serialize.</param>
  769. /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
  770. public static string SerializeXmlNode(XmlNode node)
  771. {
  772. return SerializeXmlNode(node, Formatting.None);
  773. }
  774. /// <summary>
  775. /// Serializes the <see cref="XmlNode"/> to a JSON string using formatting.
  776. /// </summary>
  777. /// <param name="node">The node to serialize.</param>
  778. /// <param name="formatting">Indicates how the output should be formatted.</param>
  779. /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
  780. public static string SerializeXmlNode(XmlNode node, Formatting formatting)
  781. {
  782. XmlNodeConverter converter = new XmlNodeConverter();
  783. return SerializeObject(node, formatting, converter);
  784. }
  785. /// <summary>
  786. /// Serializes the <see cref="XmlNode"/> to a JSON string using formatting and omits the root object if <paramref name="omitRootObject"/> is <c>true</c>.
  787. /// </summary>
  788. /// <param name="node">The node to serialize.</param>
  789. /// <param name="formatting">Indicates how the output should be formatted.</param>
  790. /// <param name="omitRootObject">Omits writing the root object.</param>
  791. /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
  792. public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject)
  793. {
  794. XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
  795. return SerializeObject(node, formatting, converter);
  796. }
  797. /// <summary>
  798. /// Deserializes the <see cref="XmlNode"/> from a JSON string.
  799. /// </summary>
  800. /// <param name="value">The JSON string.</param>
  801. /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
  802. public static XmlDocument DeserializeXmlNode(string value)
  803. {
  804. return DeserializeXmlNode(value, null);
  805. }
  806. /// <summary>
  807. /// Deserializes the <see cref="XmlNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>.
  808. /// </summary>
  809. /// <param name="value">The JSON string.</param>
  810. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  811. /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
  812. public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName)
  813. {
  814. return DeserializeXmlNode(value, deserializeRootElementName, false);
  815. }
  816. /// <summary>
  817. /// Deserializes the <see cref="XmlNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>
  818. /// and writes a Json.NET array attribute for collections.
  819. /// </summary>
  820. /// <param name="value">The JSON string.</param>
  821. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  822. /// <param name="writeArrayAttribute">
  823. /// A flag to indicate whether to write the Json.NET array attribute.
  824. /// This attribute helps preserve arrays when converting the written XML back to JSON.
  825. /// </param>
  826. /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
  827. public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
  828. {
  829. XmlNodeConverter converter = new XmlNodeConverter();
  830. converter.DeserializeRootElementName = deserializeRootElementName;
  831. converter.WriteArrayAttribute = writeArrayAttribute;
  832. return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
  833. }
  834. #if !NET20
  835. /// <summary>
  836. /// Serializes the <see cref="XNode"/> to a JSON string.
  837. /// </summary>
  838. /// <param name="node">The node to convert to JSON.</param>
  839. /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
  840. public static string SerializeXNode(XObject node)
  841. {
  842. return SerializeXNode(node, Formatting.None);
  843. }
  844. /// <summary>
  845. /// Serializes the <see cref="XNode"/> to a JSON string using formatting.
  846. /// </summary>
  847. /// <param name="node">The node to convert to JSON.</param>
  848. /// <param name="formatting">Indicates how the output should be formatted.</param>
  849. /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
  850. public static string SerializeXNode(XObject node, Formatting formatting)
  851. {
  852. return SerializeXNode(node, formatting, false);
  853. }
  854. /// <summary>
  855. /// Serializes the <see cref="XNode"/> to a JSON string using formatting and omits the root object if <paramref name="omitRootObject"/> is <c>true</c>.
  856. /// </summary>
  857. /// <param name="node">The node to serialize.</param>
  858. /// <param name="formatting">Indicates how the output should be formatted.</param>
  859. /// <param name="omitRootObject">Omits writing the root object.</param>
  860. /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
  861. public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject)
  862. {
  863. XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
  864. return SerializeObject(node, formatting, converter);
  865. }
  866. /// <summary>
  867. /// Deserializes the <see cref="XNode"/> from a JSON string.
  868. /// </summary>
  869. /// <param name="value">The JSON string.</param>
  870. /// <returns>The deserialized <see cref="XNode"/>.</returns>
  871. public static XDocument DeserializeXNode(string value)
  872. {
  873. return DeserializeXNode(value, null);
  874. }
  875. /// <summary>
  876. /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>.
  877. /// </summary>
  878. /// <param name="value">The JSON string.</param>
  879. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  880. /// <returns>The deserialized <see cref="XNode"/>.</returns>
  881. public static XDocument DeserializeXNode(string value, string deserializeRootElementName)
  882. {
  883. return DeserializeXNode(value, deserializeRootElementName, false);
  884. }
  885. /// <summary>
  886. /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>
  887. /// and writes a Json.NET array attribute for collections.
  888. /// </summary>
  889. /// <param name="value">The JSON string.</param>
  890. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  891. /// <param name="writeArrayAttribute">
  892. /// A flag to indicate whether to write the Json.NET array attribute.
  893. /// This attribute helps preserve arrays when converting the written XML back to JSON.
  894. /// </param>
  895. /// <returns>The deserialized <see cref="XNode"/>.</returns>
  896. public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
  897. {
  898. XmlNodeConverter converter = new XmlNodeConverter();
  899. converter.DeserializeRootElementName = deserializeRootElementName;
  900. converter.WriteArrayAttribute = writeArrayAttribute;
  901. return (XDocument)DeserializeObject(value, typeof(XDocument), converter);
  902. }
  903. #endif
  904. #endregion
  905. }
  906. }