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

  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. [CLSCompliant(false)]
  191. public static string ToString(ushort value)
  192. {
  193. return value.ToString(null, CultureInfo.InvariantCulture);
  194. }
  195. /// <summary>
  196. /// Converts the <see cref="UInt32"/> to its JSON string representation.
  197. /// </summary>
  198. /// <param name="value">The value to convert.</param>
  199. /// <returns>A JSON string representation of the <see cref="UInt32"/>.</returns>
  200. [CLSCompliant(false)]
  201. public static string ToString(uint value)
  202. {
  203. return value.ToString(null, CultureInfo.InvariantCulture);
  204. }
  205. /// <summary>
  206. /// Converts the <see cref="Int64"/> to its JSON string representation.
  207. /// </summary>
  208. /// <param name="value">The value to convert.</param>
  209. /// <returns>A JSON string representation of the <see cref="Int64"/>.</returns>
  210. public static string ToString(long value)
  211. {
  212. return value.ToString(null, CultureInfo.InvariantCulture);
  213. }
  214. #if HAVE_BIG_INTEGER
  215. private static string ToStringInternal(BigInteger value)
  216. {
  217. return value.ToString(null, CultureInfo.InvariantCulture);
  218. }
  219. #endif
  220. /// <summary>
  221. /// Converts the <see cref="UInt64"/> to its JSON string representation.
  222. /// </summary>
  223. /// <param name="value">The value to convert.</param>
  224. /// <returns>A JSON string representation of the <see cref="UInt64"/>.</returns>
  225. [CLSCompliant(false)]
  226. public static string ToString(ulong value)
  227. {
  228. return value.ToString(null, CultureInfo.InvariantCulture);
  229. }
  230. /// <summary>
  231. /// Converts the <see cref="Single"/> to its JSON string representation.
  232. /// </summary>
  233. /// <param name="value">The value to convert.</param>
  234. /// <returns>A JSON string representation of the <see cref="Single"/>.</returns>
  235. public static string ToString(float value)
  236. {
  237. return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
  238. }
  239. internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
  240. {
  241. return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
  242. }
  243. private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
  244. {
  245. if (floatFormatHandling == FloatFormatHandling.Symbol || !(double.IsInfinity(value) || double.IsNaN(value)))
  246. {
  247. return text;
  248. }
  249. if (floatFormatHandling == FloatFormatHandling.DefaultValue)
  250. {
  251. return (!nullable) ? "0.0" : Null;
  252. }
  253. return quoteChar + text + quoteChar;
  254. }
  255. /// <summary>
  256. /// Converts the <see cref="Double"/> to its JSON string representation.
  257. /// </summary>
  258. /// <param name="value">The value to convert.</param>
  259. /// <returns>A JSON string representation of the <see cref="Double"/>.</returns>
  260. public static string ToString(double value)
  261. {
  262. return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
  263. }
  264. internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
  265. {
  266. return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
  267. }
  268. private static string EnsureDecimalPlace(double value, string text)
  269. {
  270. if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1)
  271. {
  272. return text;
  273. }
  274. return text + ".0";
  275. }
  276. private static string EnsureDecimalPlace(string text)
  277. {
  278. if (text.IndexOf('.') != -1)
  279. {
  280. return text;
  281. }
  282. return text + ".0";
  283. }
  284. /// <summary>
  285. /// Converts the <see cref="Byte"/> to its JSON string representation.
  286. /// </summary>
  287. /// <param name="value">The value to convert.</param>
  288. /// <returns>A JSON string representation of the <see cref="Byte"/>.</returns>
  289. public static string ToString(byte value)
  290. {
  291. return value.ToString(null, CultureInfo.InvariantCulture);
  292. }
  293. /// <summary>
  294. /// Converts the <see cref="SByte"/> to its JSON string representation.
  295. /// </summary>
  296. /// <param name="value">The value to convert.</param>
  297. /// <returns>A JSON string representation of the <see cref="SByte"/>.</returns>
  298. [CLSCompliant(false)]
  299. public static string ToString(sbyte value)
  300. {
  301. return value.ToString(null, CultureInfo.InvariantCulture);
  302. }
  303. /// <summary>
  304. /// Converts the <see cref="Decimal"/> to its JSON string representation.
  305. /// </summary>
  306. /// <param name="value">The value to convert.</param>
  307. /// <returns>A JSON string representation of the <see cref="SByte"/>.</returns>
  308. public static string ToString(decimal value)
  309. {
  310. return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
  311. }
  312. /// <summary>
  313. /// Converts the <see cref="Guid"/> to its JSON string representation.
  314. /// </summary>
  315. /// <param name="value">The value to convert.</param>
  316. /// <returns>A JSON string representation of the <see cref="Guid"/>.</returns>
  317. public static string ToString(Guid value)
  318. {
  319. return ToString(value, '"');
  320. }
  321. internal static string ToString(Guid value, char quoteChar)
  322. {
  323. string text;
  324. string qc;
  325. #if HAVE_CHAR_TO_STRING_WITH_CULTURE
  326. text = value.ToString("D", CultureInfo.InvariantCulture);
  327. qc = quoteChar.ToString(CultureInfo.InvariantCulture);
  328. #else
  329. text = value.ToString("D");
  330. qc = quoteChar.ToString();
  331. #endif
  332. return qc + text + qc;
  333. }
  334. /// <summary>
  335. /// Converts the <see cref="TimeSpan"/> to its JSON string representation.
  336. /// </summary>
  337. /// <param name="value">The value to convert.</param>
  338. /// <returns>A JSON string representation of the <see cref="TimeSpan"/>.</returns>
  339. public static string ToString(TimeSpan value)
  340. {
  341. return ToString(value, '"');
  342. }
  343. internal static string ToString(TimeSpan value, char quoteChar)
  344. {
  345. return ToString(value.ToString(), quoteChar);
  346. }
  347. /// <summary>
  348. /// Converts the <see cref="Uri"/> to its JSON string representation.
  349. /// </summary>
  350. /// <param name="value">The value to convert.</param>
  351. /// <returns>A JSON string representation of the <see cref="Uri"/>.</returns>
  352. public static string ToString(Uri value)
  353. {
  354. if (value == null)
  355. {
  356. return Null;
  357. }
  358. return ToString(value, '"');
  359. }
  360. internal static string ToString(Uri value, char quoteChar)
  361. {
  362. return ToString(value.OriginalString, quoteChar);
  363. }
  364. /// <summary>
  365. /// Converts the <see cref="String"/> to its JSON string representation.
  366. /// </summary>
  367. /// <param name="value">The value to convert.</param>
  368. /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
  369. public static string ToString(string value)
  370. {
  371. return ToString(value, '"');
  372. }
  373. /// <summary>
  374. /// Converts the <see cref="String"/> to its JSON string representation.
  375. /// </summary>
  376. /// <param name="value">The value to convert.</param>
  377. /// <param name="delimiter">The string delimiter character.</param>
  378. /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
  379. public static string ToString(string value, char delimiter)
  380. {
  381. return ToString(value, delimiter, StringEscapeHandling.Default);
  382. }
  383. /// <summary>
  384. /// Converts the <see cref="String"/> to its JSON string representation.
  385. /// </summary>
  386. /// <param name="value">The value to convert.</param>
  387. /// <param name="delimiter">The string delimiter character.</param>
  388. /// <param name="stringEscapeHandling">The string escape handling.</param>
  389. /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
  390. public static string ToString(string value, char delimiter, StringEscapeHandling stringEscapeHandling)
  391. {
  392. if (delimiter != '"' && delimiter != '\'')
  393. {
  394. throw new ArgumentException("Delimiter must be a single or double quote.", nameof(delimiter));
  395. }
  396. return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, true, stringEscapeHandling);
  397. }
  398. /// <summary>
  399. /// Converts the <see cref="Object"/> to its JSON string representation.
  400. /// </summary>
  401. /// <param name="value">The value to convert.</param>
  402. /// <returns>A JSON string representation of the <see cref="Object"/>.</returns>
  403. public static string ToString(object value)
  404. {
  405. if (value == null)
  406. {
  407. return Null;
  408. }
  409. PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value.GetType());
  410. switch (typeCode)
  411. {
  412. case PrimitiveTypeCode.String:
  413. return ToString((string)value);
  414. case PrimitiveTypeCode.Char:
  415. return ToString((char)value);
  416. case PrimitiveTypeCode.Boolean:
  417. return ToString((bool)value);
  418. case PrimitiveTypeCode.SByte:
  419. return ToString((sbyte)value);
  420. case PrimitiveTypeCode.Int16:
  421. return ToString((short)value);
  422. case PrimitiveTypeCode.UInt16:
  423. return ToString((ushort)value);
  424. case PrimitiveTypeCode.Int32:
  425. return ToString((int)value);
  426. case PrimitiveTypeCode.Byte:
  427. return ToString((byte)value);
  428. case PrimitiveTypeCode.UInt32:
  429. return ToString((uint)value);
  430. case PrimitiveTypeCode.Int64:
  431. return ToString((long)value);
  432. case PrimitiveTypeCode.UInt64:
  433. return ToString((ulong)value);
  434. case PrimitiveTypeCode.Single:
  435. return ToString((float)value);
  436. case PrimitiveTypeCode.Double:
  437. return ToString((double)value);
  438. case PrimitiveTypeCode.DateTime:
  439. return ToString((DateTime)value);
  440. case PrimitiveTypeCode.Decimal:
  441. return ToString((decimal)value);
  442. case PrimitiveTypeCode.DBNull:
  443. return Null;
  444. #if !NET20
  445. case PrimitiveTypeCode.DateTimeOffset:
  446. return ToString((DateTimeOffset)value);
  447. #endif
  448. case PrimitiveTypeCode.Guid:
  449. return ToString((Guid)value);
  450. case PrimitiveTypeCode.Uri:
  451. return ToString((Uri)value);
  452. case PrimitiveTypeCode.TimeSpan:
  453. return ToString((TimeSpan)value);
  454. #if HAVE_BIG_INTEGER
  455. case PrimitiveTypeCode.BigInteger:
  456. return ToStringInternal((BigInteger)value);
  457. #endif
  458. }
  459. throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
  460. }
  461. #region Serialize
  462. /// <summary>
  463. /// Serializes the specified object to a JSON string.
  464. /// </summary>
  465. /// <param name="value">The object to serialize.</param>
  466. /// <returns>A JSON string representation of the object.</returns>
  467. public static string SerializeObject(object value)
  468. {
  469. return SerializeObject(value, null, (JsonSerializerSettings)null);
  470. }
  471. /// <summary>
  472. /// Serializes the specified object to a JSON string using formatting.
  473. /// </summary>
  474. /// <param name="value">The object to serialize.</param>
  475. /// <param name="formatting">Indicates how the output should be formatted.</param>
  476. /// <returns>
  477. /// A JSON string representation of the object.
  478. /// </returns>
  479. public static string SerializeObject(object value, Formatting formatting)
  480. {
  481. return SerializeObject(value, formatting, (JsonSerializerSettings)null);
  482. }
  483. /// <summary>
  484. /// Serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
  485. /// </summary>
  486. /// <param name="value">The object to serialize.</param>
  487. /// <param name="converters">A collection of converters used while serializing.</param>
  488. /// <returns>A JSON string representation of the object.</returns>
  489. public static string SerializeObject(object value, params JsonConverter[] converters)
  490. {
  491. JsonSerializerSettings settings = (converters != null && converters.Length > 0)
  492. ? new JsonSerializerSettings { Converters = converters }
  493. : null;
  494. return SerializeObject(value, null, settings);
  495. }
  496. /// <summary>
  497. /// Serializes the specified object to a JSON string using formatting and a collection of <see cref="JsonConverter"/>.
  498. /// </summary>
  499. /// <param name="value">The object to serialize.</param>
  500. /// <param name="formatting">Indicates how the output should be formatted.</param>
  501. /// <param name="converters">A collection of converters used while serializing.</param>
  502. /// <returns>A JSON string representation of the object.</returns>
  503. public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters)
  504. {
  505. JsonSerializerSettings settings = (converters != null && converters.Length > 0)
  506. ? new JsonSerializerSettings { Converters = converters }
  507. : null;
  508. return SerializeObject(value, null, formatting, settings);
  509. }
  510. /// <summary>
  511. /// Serializes the specified object to a JSON string using <see cref="JsonSerializerSettings"/>.
  512. /// </summary>
  513. /// <param name="value">The object to serialize.</param>
  514. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  515. /// If this is <c>null</c>, default serialization settings will be used.</param>
  516. /// <returns>
  517. /// A JSON string representation of the object.
  518. /// </returns>
  519. public static string SerializeObject(object value, JsonSerializerSettings settings)
  520. {
  521. return SerializeObject(value, null, settings);
  522. }
  523. /// <summary>
  524. /// Serializes the specified object to a JSON string using a type, formatting and <see cref="JsonSerializerSettings"/>.
  525. /// </summary>
  526. /// <param name="value">The object to serialize.</param>
  527. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  528. /// If this is <c>null</c>, default serialization settings will be used.</param>
  529. /// <param name="type">
  530. /// The type of the value being serialized.
  531. /// 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.
  532. /// Specifying the type is optional.
  533. /// </param>
  534. /// <returns>
  535. /// A JSON string representation of the object.
  536. /// </returns>
  537. public static string SerializeObject(object value, Type type, JsonSerializerSettings settings)
  538. {
  539. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  540. return SerializeObjectInternal(value, type, jsonSerializer);
  541. }
  542. /// <summary>
  543. /// Serializes the specified object to a JSON string using formatting and <see cref="JsonSerializerSettings"/>.
  544. /// </summary>
  545. /// <param name="value">The object to serialize.</param>
  546. /// <param name="formatting">Indicates how the output should be formatted.</param>
  547. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  548. /// If this is <c>null</c>, default serialization settings will be used.</param>
  549. /// <returns>
  550. /// A JSON string representation of the object.
  551. /// </returns>
  552. public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings)
  553. {
  554. return SerializeObject(value, null, formatting, settings);
  555. }
  556. /// <summary>
  557. /// Serializes the specified object to a JSON string using a type, formatting and <see cref="JsonSerializerSettings"/>.
  558. /// </summary>
  559. /// <param name="value">The object to serialize.</param>
  560. /// <param name="formatting">Indicates how the output should be formatted.</param>
  561. /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
  562. /// If this is <c>null</c>, default serialization settings will be used.</param>
  563. /// <param name="type">
  564. /// The type of the value being serialized.
  565. /// 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.
  566. /// Specifying the type is optional.
  567. /// </param>
  568. /// <returns>
  569. /// A JSON string representation of the object.
  570. /// </returns>
  571. public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings)
  572. {
  573. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  574. jsonSerializer.Formatting = formatting;
  575. return SerializeObjectInternal(value, type, jsonSerializer);
  576. }
  577. private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer)
  578. {
  579. StringBuilder sb = new StringBuilder(256);
  580. StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
  581. using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
  582. {
  583. jsonWriter.Formatting = jsonSerializer.Formatting;
  584. jsonSerializer.Serialize(jsonWriter, value, type);
  585. }
  586. return sw.ToString();
  587. }
  588. #endregion
  589. #region Deserialize
  590. /// <summary>
  591. /// Deserializes the JSON to a .NET object.
  592. /// </summary>
  593. /// <param name="value">The JSON to deserialize.</param>
  594. /// <returns>The deserialized object from the JSON string.</returns>
  595. public static object DeserializeObject(string value)
  596. {
  597. return DeserializeObject(value, null, (JsonSerializerSettings)null);
  598. }
  599. /// <summary>
  600. /// Deserializes the JSON to a .NET object using <see cref="JsonSerializerSettings"/>.
  601. /// </summary>
  602. /// <param name="value">The JSON to deserialize.</param>
  603. /// <param name="settings">
  604. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  605. /// If this is <c>null</c>, default serialization settings will be used.
  606. /// </param>
  607. /// <returns>The deserialized object from the JSON string.</returns>
  608. public static object DeserializeObject(string value, JsonSerializerSettings settings)
  609. {
  610. return DeserializeObject(value, null, settings);
  611. }
  612. /// <summary>
  613. /// Deserializes the JSON to the specified .NET type.
  614. /// </summary>
  615. /// <param name="value">The JSON to deserialize.</param>
  616. /// <param name="type">The <see cref="Type"/> of object being deserialized.</param>
  617. /// <returns>The deserialized object from the JSON string.</returns>
  618. public static object DeserializeObject(string value, Type type)
  619. {
  620. return DeserializeObject(value, type, (JsonSerializerSettings)null);
  621. }
  622. /// <summary>
  623. /// Deserializes the JSON to the specified .NET type.
  624. /// </summary>
  625. /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
  626. /// <param name="value">The JSON to deserialize.</param>
  627. /// <returns>The deserialized object from the JSON string.</returns>
  628. public static T DeserializeObject<T>(string value)
  629. {
  630. return DeserializeObject<T>(value, (JsonSerializerSettings)null);
  631. }
  632. /// <summary>
  633. /// Deserializes the JSON to the given anonymous type.
  634. /// </summary>
  635. /// <typeparam name="T">
  636. /// The anonymous type to deserialize to. This can't be specified
  637. /// traditionally and must be inferred from the anonymous type passed
  638. /// as a parameter.
  639. /// </typeparam>
  640. /// <param name="value">The JSON to deserialize.</param>
  641. /// <param name="anonymousTypeObject">The anonymous type object.</param>
  642. /// <returns>The deserialized anonymous type from the JSON string.</returns>
  643. public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
  644. {
  645. return DeserializeObject<T>(value);
  646. }
  647. /// <summary>
  648. /// Deserializes the JSON to the given anonymous type using <see cref="JsonSerializerSettings"/>.
  649. /// </summary>
  650. /// <typeparam name="T">
  651. /// The anonymous type to deserialize to. This can't be specified
  652. /// traditionally and must be inferred from the anonymous type passed
  653. /// as a parameter.
  654. /// </typeparam>
  655. /// <param name="value">The JSON to deserialize.</param>
  656. /// <param name="anonymousTypeObject">The anonymous type object.</param>
  657. /// <param name="settings">
  658. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  659. /// If this is <c>null</c>, default serialization settings will be used.
  660. /// </param>
  661. /// <returns>The deserialized anonymous type from the JSON string.</returns>
  662. public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
  663. {
  664. return DeserializeObject<T>(value, settings);
  665. }
  666. /// <summary>
  667. /// Deserializes the JSON to the specified .NET type using a collection of <see cref="JsonConverter"/>.
  668. /// </summary>
  669. /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
  670. /// <param name="value">The JSON to deserialize.</param>
  671. /// <param name="converters">Converters to use while deserializing.</param>
  672. /// <returns>The deserialized object from the JSON string.</returns>
  673. public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
  674. {
  675. return (T)DeserializeObject(value, typeof(T), converters);
  676. }
  677. /// <summary>
  678. /// Deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
  679. /// </summary>
  680. /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
  681. /// <param name="value">The object to deserialize.</param>
  682. /// <param name="settings">
  683. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  684. /// If this is <c>null</c>, default serialization settings will be used.
  685. /// </param>
  686. /// <returns>The deserialized object from the JSON string.</returns>
  687. public static T DeserializeObject<T>(string value, JsonSerializerSettings settings)
  688. {
  689. return (T)DeserializeObject(value, typeof(T), settings);
  690. }
  691. /// <summary>
  692. /// Deserializes the JSON to the specified .NET type using a collection of <see cref="JsonConverter"/>.
  693. /// </summary>
  694. /// <param name="value">The JSON to deserialize.</param>
  695. /// <param name="type">The type of the object to deserialize.</param>
  696. /// <param name="converters">Converters to use while deserializing.</param>
  697. /// <returns>The deserialized object from the JSON string.</returns>
  698. public static object DeserializeObject(string value, Type type, params JsonConverter[] converters)
  699. {
  700. JsonSerializerSettings settings = (converters != null && converters.Length > 0)
  701. ? new JsonSerializerSettings { Converters = converters }
  702. : null;
  703. return DeserializeObject(value, type, settings);
  704. }
  705. /// <summary>
  706. /// Deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
  707. /// </summary>
  708. /// <param name="value">The JSON to deserialize.</param>
  709. /// <param name="type">The type of the object to deserialize to.</param>
  710. /// <param name="settings">
  711. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  712. /// If this is <c>null</c>, default serialization settings will be used.
  713. /// </param>
  714. /// <returns>The deserialized object from the JSON string.</returns>
  715. public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings)
  716. {
  717. ValidationUtils.ArgumentNotNull(value, nameof(value));
  718. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  719. // by default DeserializeObject should check for additional content
  720. if (!jsonSerializer.IsCheckAdditionalContentSet())
  721. {
  722. jsonSerializer.CheckAdditionalContent = true;
  723. }
  724. using (JsonTextReader reader = new JsonTextReader(new StringReader(value)))
  725. {
  726. return jsonSerializer.Deserialize(reader, type);
  727. }
  728. }
  729. #endregion
  730. #region Populate
  731. /// <summary>
  732. /// Populates the object with values from the JSON string.
  733. /// </summary>
  734. /// <param name="value">The JSON to populate values from.</param>
  735. /// <param name="target">The target object to populate values onto.</param>
  736. public static void PopulateObject(string value, object target)
  737. {
  738. PopulateObject(value, target, null);
  739. }
  740. /// <summary>
  741. /// Populates the object with values from the JSON string using <see cref="JsonSerializerSettings"/>.
  742. /// </summary>
  743. /// <param name="value">The JSON to populate values from.</param>
  744. /// <param name="target">The target object to populate values onto.</param>
  745. /// <param name="settings">
  746. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
  747. /// If this is <c>null</c>, default serialization settings will be used.
  748. /// </param>
  749. public static void PopulateObject(string value, object target, JsonSerializerSettings settings)
  750. {
  751. JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
  752. using (JsonReader jsonReader = new JsonTextReader(new StringReader(value)))
  753. {
  754. jsonSerializer.Populate(jsonReader, target);
  755. if (settings != null && settings.CheckAdditionalContent)
  756. {
  757. while (jsonReader.Read())
  758. {
  759. if (jsonReader.TokenType != JsonToken.Comment)
  760. {
  761. throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object.");
  762. }
  763. }
  764. }
  765. }
  766. }
  767. #endregion
  768. #region Xml
  769. /// <summary>
  770. /// Serializes the <see cref="XmlNode"/> to a JSON string.
  771. /// </summary>
  772. /// <param name="node">The node to serialize.</param>
  773. /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
  774. public static string SerializeXmlNode(XmlNode node)
  775. {
  776. return SerializeXmlNode(node, Formatting.None);
  777. }
  778. /// <summary>
  779. /// Serializes the <see cref="XmlNode"/> to a JSON string using formatting.
  780. /// </summary>
  781. /// <param name="node">The node to serialize.</param>
  782. /// <param name="formatting">Indicates how the output should be formatted.</param>
  783. /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
  784. public static string SerializeXmlNode(XmlNode node, Formatting formatting)
  785. {
  786. XmlNodeConverter converter = new XmlNodeConverter();
  787. return SerializeObject(node, formatting, converter);
  788. }
  789. /// <summary>
  790. /// Serializes the <see cref="XmlNode"/> to a JSON string using formatting and omits the root object if <paramref name="omitRootObject"/> is <c>true</c>.
  791. /// </summary>
  792. /// <param name="node">The node to serialize.</param>
  793. /// <param name="formatting">Indicates how the output should be formatted.</param>
  794. /// <param name="omitRootObject">Omits writing the root object.</param>
  795. /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
  796. public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject)
  797. {
  798. XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
  799. return SerializeObject(node, formatting, converter);
  800. }
  801. /// <summary>
  802. /// Deserializes the <see cref="XmlNode"/> from a JSON string.
  803. /// </summary>
  804. /// <param name="value">The JSON string.</param>
  805. /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
  806. public static XmlDocument DeserializeXmlNode(string value)
  807. {
  808. return DeserializeXmlNode(value, null);
  809. }
  810. /// <summary>
  811. /// Deserializes the <see cref="XmlNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>.
  812. /// </summary>
  813. /// <param name="value">The JSON string.</param>
  814. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  815. /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
  816. public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName)
  817. {
  818. return DeserializeXmlNode(value, deserializeRootElementName, false);
  819. }
  820. /// <summary>
  821. /// Deserializes the <see cref="XmlNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>
  822. /// and writes a Json.NET array attribute for collections.
  823. /// </summary>
  824. /// <param name="value">The JSON string.</param>
  825. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  826. /// <param name="writeArrayAttribute">
  827. /// A flag to indicate whether to write the Json.NET array attribute.
  828. /// This attribute helps preserve arrays when converting the written XML back to JSON.
  829. /// </param>
  830. /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
  831. public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
  832. {
  833. XmlNodeConverter converter = new XmlNodeConverter();
  834. converter.DeserializeRootElementName = deserializeRootElementName;
  835. converter.WriteArrayAttribute = writeArrayAttribute;
  836. return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
  837. }
  838. #if !NET20
  839. /// <summary>
  840. /// Serializes the <see cref="XNode"/> to a JSON string.
  841. /// </summary>
  842. /// <param name="node">The node to convert to JSON.</param>
  843. /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
  844. public static string SerializeXNode(XObject node)
  845. {
  846. return SerializeXNode(node, Formatting.None);
  847. }
  848. /// <summary>
  849. /// Serializes the <see cref="XNode"/> to a JSON string using formatting.
  850. /// </summary>
  851. /// <param name="node">The node to convert to JSON.</param>
  852. /// <param name="formatting">Indicates how the output should be formatted.</param>
  853. /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
  854. public static string SerializeXNode(XObject node, Formatting formatting)
  855. {
  856. return SerializeXNode(node, formatting, false);
  857. }
  858. /// <summary>
  859. /// Serializes the <see cref="XNode"/> to a JSON string using formatting and omits the root object if <paramref name="omitRootObject"/> is <c>true</c>.
  860. /// </summary>
  861. /// <param name="node">The node to serialize.</param>
  862. /// <param name="formatting">Indicates how the output should be formatted.</param>
  863. /// <param name="omitRootObject">Omits writing the root object.</param>
  864. /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
  865. public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject)
  866. {
  867. XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
  868. return SerializeObject(node, formatting, converter);
  869. }
  870. /// <summary>
  871. /// Deserializes the <see cref="XNode"/> from a JSON string.
  872. /// </summary>
  873. /// <param name="value">The JSON string.</param>
  874. /// <returns>The deserialized <see cref="XNode"/>.</returns>
  875. public static XDocument DeserializeXNode(string value)
  876. {
  877. return DeserializeXNode(value, null);
  878. }
  879. /// <summary>
  880. /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>.
  881. /// </summary>
  882. /// <param name="value">The JSON string.</param>
  883. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  884. /// <returns>The deserialized <see cref="XNode"/>.</returns>
  885. public static XDocument DeserializeXNode(string value, string deserializeRootElementName)
  886. {
  887. return DeserializeXNode(value, deserializeRootElementName, false);
  888. }
  889. /// <summary>
  890. /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root element specified by <paramref name="deserializeRootElementName"/>
  891. /// and writes a Json.NET array attribute for collections.
  892. /// </summary>
  893. /// <param name="value">The JSON string.</param>
  894. /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
  895. /// <param name="writeArrayAttribute">
  896. /// A flag to indicate whether to write the Json.NET array attribute.
  897. /// This attribute helps preserve arrays when converting the written XML back to JSON.
  898. /// </param>
  899. /// <returns>The deserialized <see cref="XNode"/>.</returns>
  900. public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
  901. {
  902. XmlNodeConverter converter = new XmlNodeConverter();
  903. converter.DeserializeRootElementName = deserializeRootElementName;
  904. converter.WriteArrayAttribute = writeArrayAttribute;
  905. return (XDocument)DeserializeObject(value, typeof(XDocument), converter);
  906. }
  907. #endif
  908. #endregion
  909. }
  910. }