PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs

https://bitbucket.org/Ecarestia/newtonsoft.json
C# | 2420 lines | 2371 code | 18 blank | 31 comment | 3 complexity | 3e2923cf9a3c4a227ed7b21a1a9caebf MD5 | raw file
  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. #if NET20
  26. using Newtonsoft.Json.Utilities.LinqBridge;
  27. #else
  28. using System.Linq;
  29. #endif
  30. #if !(PORTABLE || PORTABLE40)
  31. using System.Collections.ObjectModel;
  32. #if !(NET35 || NET20)
  33. using System.Dynamic;
  34. #endif
  35. using System.Text;
  36. using Newtonsoft.Json.Tests.Linq;
  37. using System;
  38. using System.Collections;
  39. using System.Collections.Generic;
  40. using System.Globalization;
  41. using System.Runtime.Serialization.Formatters;
  42. using Newtonsoft.Json.Linq;
  43. using Newtonsoft.Json.Serialization;
  44. using Newtonsoft.Json.Tests.TestObjects;
  45. using Newtonsoft.Json.Tests.TestObjects.Organization;
  46. #if DNXCORE50
  47. using Xunit;
  48. using Test = Xunit.FactAttribute;
  49. using Assert = Newtonsoft.Json.Tests.XUnitAssert;
  50. #else
  51. using NUnit.Framework;
  52. #endif
  53. using Newtonsoft.Json.Utilities;
  54. using System.Net;
  55. using System.Runtime.Serialization;
  56. using System.IO;
  57. namespace Newtonsoft.Json.Tests.Serialization
  58. {
  59. [TestFixture]
  60. public class TypeNameHandlingTests : TestFixtureBase
  61. {
  62. #if !(NET20 || NET35)
  63. [Test]
  64. public void SerializeValueTupleWithTypeName()
  65. {
  66. string tupleRef = ReflectionUtils.GetTypeName(typeof(ValueTuple<int, int, string>), TypeNameAssemblyFormatHandling.Simple, null);
  67. ValueTuple<int, int, string> t = ValueTuple.Create(1, 2, "string");
  68. string json = JsonConvert.SerializeObject(t, Formatting.Indented, new JsonSerializerSettings
  69. {
  70. TypeNameHandling = TypeNameHandling.All
  71. });
  72. StringAssert.AreEqual(@"{
  73. ""$type"": """ + tupleRef + @""",
  74. ""Item1"": 1,
  75. ""Item2"": 2,
  76. ""Item3"": ""string""
  77. }", json);
  78. ValueTuple<int, int, string> t2 = (ValueTuple<int, int, string>)JsonConvert.DeserializeObject(json, new JsonSerializerSettings
  79. {
  80. TypeNameHandling = TypeNameHandling.All
  81. });
  82. Assert.AreEqual(1, t2.Item1);
  83. Assert.AreEqual(2, t2.Item2);
  84. Assert.AreEqual("string", t2.Item3);
  85. }
  86. #endif
  87. #if !(NET20 || NET35 || NET40)
  88. public class KnownAutoTypes
  89. {
  90. public ICollection<string> Collection { get; set; }
  91. public IList<string> List { get; set; }
  92. public IDictionary<string, string> Dictionary { get; set; }
  93. public ISet<string> Set { get; set; }
  94. public IReadOnlyCollection<string> ReadOnlyCollection { get; set; }
  95. public IReadOnlyList<string> ReadOnlyList { get; set; }
  96. public IReadOnlyDictionary<string, string> ReadOnlyDictionary { get; set; }
  97. }
  98. [Test]
  99. public void KnownAutoTypesTest()
  100. {
  101. KnownAutoTypes c = new KnownAutoTypes
  102. {
  103. Collection = new List<string> { "Collection value!" },
  104. List = new List<string> { "List value!" },
  105. Dictionary = new Dictionary<string, string>
  106. {
  107. { "Dictionary key!", "Dictionary value!" }
  108. },
  109. ReadOnlyCollection = new ReadOnlyCollection<string>(new[] { "Read Only Collection value!" }),
  110. ReadOnlyList = new ReadOnlyCollection<string>(new[] { "Read Only List value!" }),
  111. Set = new HashSet<string> { "Set value!" },
  112. ReadOnlyDictionary = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>
  113. {
  114. { "Read Only Dictionary key!", "Read Only Dictionary value!" }
  115. })
  116. };
  117. string json = JsonConvert.SerializeObject(c, Formatting.Indented, new JsonSerializerSettings
  118. {
  119. TypeNameHandling = TypeNameHandling.Auto
  120. });
  121. StringAssert.AreEqual(@"{
  122. ""Collection"": [
  123. ""Collection value!""
  124. ],
  125. ""List"": [
  126. ""List value!""
  127. ],
  128. ""Dictionary"": {
  129. ""Dictionary key!"": ""Dictionary value!""
  130. },
  131. ""Set"": [
  132. ""Set value!""
  133. ],
  134. ""ReadOnlyCollection"": [
  135. ""Read Only Collection value!""
  136. ],
  137. ""ReadOnlyList"": [
  138. ""Read Only List value!""
  139. ],
  140. ""ReadOnlyDictionary"": {
  141. ""Read Only Dictionary key!"": ""Read Only Dictionary value!""
  142. }
  143. }", json);
  144. }
  145. #endif
  146. [Test]
  147. public void DictionaryAuto()
  148. {
  149. Dictionary<string, object> dic = new Dictionary<string, object>
  150. {
  151. { "movie", new Movie { Name = "Die Hard" } }
  152. };
  153. string json = JsonConvert.SerializeObject(dic, Formatting.Indented, new JsonSerializerSettings
  154. {
  155. TypeNameHandling = TypeNameHandling.Auto
  156. });
  157. StringAssert.AreEqual(@"{
  158. ""movie"": {
  159. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Movie, Newtonsoft.Json.Tests"",
  160. ""Name"": ""Die Hard"",
  161. ""Description"": null,
  162. ""Classification"": null,
  163. ""Studio"": null,
  164. ""ReleaseDate"": null,
  165. ""ReleaseCountries"": null
  166. }
  167. }", json);
  168. }
  169. [Test]
  170. public void KeyValuePairAuto()
  171. {
  172. IList<KeyValuePair<string, object>> dic = new List<KeyValuePair<string, object>>
  173. {
  174. new KeyValuePair<string, object>("movie", new Movie { Name = "Die Hard" })
  175. };
  176. string json = JsonConvert.SerializeObject(dic, Formatting.Indented, new JsonSerializerSettings
  177. {
  178. TypeNameHandling = TypeNameHandling.Auto
  179. });
  180. StringAssert.AreEqual(@"[
  181. {
  182. ""Key"": ""movie"",
  183. ""Value"": {
  184. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Movie, Newtonsoft.Json.Tests"",
  185. ""Name"": ""Die Hard"",
  186. ""Description"": null,
  187. ""Classification"": null,
  188. ""Studio"": null,
  189. ""ReleaseDate"": null,
  190. ""ReleaseCountries"": null
  191. }
  192. }
  193. ]", json);
  194. }
  195. [Test]
  196. public void NestedValueObjects()
  197. {
  198. StringBuilder sb = new StringBuilder();
  199. for (int i = 0; i < 3; i++)
  200. {
  201. sb.Append(@"{""$value"":");
  202. }
  203. ExceptionAssert.Throws<JsonSerializationException>(() =>
  204. {
  205. var reader = new JsonTextReader(new StringReader(sb.ToString()));
  206. var ser = new JsonSerializer();
  207. ser.MetadataPropertyHandling = MetadataPropertyHandling.Default;
  208. ser.Deserialize<sbyte>(reader);
  209. }, "Unexpected token when deserializing primitive value: StartObject. Path '$value', line 1, position 11.");
  210. }
  211. [Test]
  212. public void SerializeRootTypeNameIfDerivedWithAuto()
  213. {
  214. var serializer = new JsonSerializer()
  215. {
  216. TypeNameHandling = TypeNameHandling.Auto
  217. };
  218. var sw = new StringWriter();
  219. serializer.Serialize(new JsonTextWriter(sw) { Formatting = Formatting.Indented }, new WagePerson(), typeof(Person));
  220. var result = sw.ToString();
  221. StringAssert.AreEqual(@"{
  222. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Organization.WagePerson, Newtonsoft.Json.Tests"",
  223. ""HourlyWage"": 0.0,
  224. ""Name"": null,
  225. ""BirthDate"": ""0001-01-01T00:00:00"",
  226. ""LastModified"": ""0001-01-01T00:00:00""
  227. }", result);
  228. Assert.IsTrue(result.Contains("WagePerson"));
  229. using (var rd = new JsonTextReader(new StringReader(result)))
  230. {
  231. var person = serializer.Deserialize<Person>(rd);
  232. CustomAssert.IsInstanceOfType(typeof(WagePerson), person);
  233. }
  234. }
  235. [Test]
  236. public void SerializeRootTypeNameAutoWithJsonConvert()
  237. {
  238. string json = JsonConvert.SerializeObject(new WagePerson(), typeof(object), Formatting.Indented, new JsonSerializerSettings
  239. {
  240. TypeNameHandling = TypeNameHandling.Auto
  241. });
  242. StringAssert.AreEqual(@"{
  243. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Organization.WagePerson, Newtonsoft.Json.Tests"",
  244. ""HourlyWage"": 0.0,
  245. ""Name"": null,
  246. ""BirthDate"": ""0001-01-01T00:00:00"",
  247. ""LastModified"": ""0001-01-01T00:00:00""
  248. }", json);
  249. }
  250. [Test]
  251. public void SerializeRootTypeNameAutoWithJsonConvert_Generic()
  252. {
  253. string json = JsonConvert.SerializeObject(new WagePerson(), typeof(object), Formatting.Indented, new JsonSerializerSettings
  254. {
  255. TypeNameHandling = TypeNameHandling.Auto
  256. });
  257. StringAssert.AreEqual(@"{
  258. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Organization.WagePerson, Newtonsoft.Json.Tests"",
  259. ""HourlyWage"": 0.0,
  260. ""Name"": null,
  261. ""BirthDate"": ""0001-01-01T00:00:00"",
  262. ""LastModified"": ""0001-01-01T00:00:00""
  263. }", json);
  264. }
  265. [Test]
  266. public void SerializeRootTypeNameAutoWithJsonConvert_Generic2()
  267. {
  268. string json = JsonConvert.SerializeObject(new WagePerson(), typeof(object), new JsonSerializerSettings
  269. {
  270. TypeNameHandling = TypeNameHandling.Auto
  271. });
  272. StringAssert.AreEqual(@"{""$type"":""Newtonsoft.Json.Tests.TestObjects.Organization.WagePerson, Newtonsoft.Json.Tests"",""HourlyWage"":0.0,""Name"":null,""BirthDate"":""0001-01-01T00:00:00"",""LastModified"":""0001-01-01T00:00:00""}", json);
  273. }
  274. public class Wrapper
  275. {
  276. public IList<EmployeeReference> Array { get; set; }
  277. public IDictionary<string, EmployeeReference> Dictionary { get; set; }
  278. }
  279. [Test]
  280. public void SerializeWrapper()
  281. {
  282. Wrapper wrapper = new Wrapper();
  283. wrapper.Array = new List<EmployeeReference>
  284. {
  285. new EmployeeReference()
  286. };
  287. wrapper.Dictionary = new Dictionary<string, EmployeeReference>
  288. {
  289. { "First", new EmployeeReference() }
  290. };
  291. string json = JsonConvert.SerializeObject(wrapper, Formatting.Indented, new JsonSerializerSettings
  292. {
  293. TypeNameHandling = TypeNameHandling.Auto
  294. });
  295. StringAssert.AreEqual(@"{
  296. ""Array"": [
  297. {
  298. ""$id"": ""1"",
  299. ""Name"": null,
  300. ""Manager"": null
  301. }
  302. ],
  303. ""Dictionary"": {
  304. ""First"": {
  305. ""$id"": ""2"",
  306. ""Name"": null,
  307. ""Manager"": null
  308. }
  309. }
  310. }", json);
  311. Wrapper w2 = JsonConvert.DeserializeObject<Wrapper>(json);
  312. CustomAssert.IsInstanceOfType(typeof(List<EmployeeReference>), w2.Array);
  313. CustomAssert.IsInstanceOfType(typeof(Dictionary<string, EmployeeReference>), w2.Dictionary);
  314. }
  315. [Test]
  316. public void WriteTypeNameForObjects()
  317. {
  318. string employeeRef = ReflectionUtils.GetTypeName(typeof(EmployeeReference), TypeNameAssemblyFormatHandling.Simple, null);
  319. EmployeeReference employee = new EmployeeReference();
  320. string json = JsonConvert.SerializeObject(employee, Formatting.Indented, new JsonSerializerSettings
  321. {
  322. TypeNameHandling = TypeNameHandling.Objects
  323. });
  324. StringAssert.AreEqual(@"{
  325. ""$id"": ""1"",
  326. ""$type"": """ + employeeRef + @""",
  327. ""Name"": null,
  328. ""Manager"": null
  329. }", json);
  330. }
  331. [Test]
  332. public void DeserializeTypeName()
  333. {
  334. string employeeRef = ReflectionUtils.GetTypeName(typeof(EmployeeReference), TypeNameAssemblyFormatHandling.Simple, null);
  335. string json = @"{
  336. ""$id"": ""1"",
  337. ""$type"": """ + employeeRef + @""",
  338. ""Name"": ""Name!"",
  339. ""Manager"": null
  340. }";
  341. object employee = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
  342. {
  343. TypeNameHandling = TypeNameHandling.Objects
  344. });
  345. CustomAssert.IsInstanceOfType(typeof(EmployeeReference), employee);
  346. Assert.AreEqual("Name!", ((EmployeeReference)employee).Name);
  347. }
  348. #if !(PORTABLE || DNXCORE50)
  349. [Test]
  350. public void DeserializeTypeNameFromGacAssembly()
  351. {
  352. string cookieRef = ReflectionUtils.GetTypeName(typeof(Cookie), TypeNameAssemblyFormatHandling.Simple, null);
  353. string json = @"{
  354. ""$id"": ""1"",
  355. ""$type"": """ + cookieRef + @"""
  356. }";
  357. object cookie = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
  358. {
  359. TypeNameHandling = TypeNameHandling.Objects
  360. });
  361. CustomAssert.IsInstanceOfType(typeof(Cookie), cookie);
  362. }
  363. #endif
  364. [Test]
  365. public void SerializeGenericObjectListWithTypeName()
  366. {
  367. string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
  368. string personRef = typeof(Person).AssemblyQualifiedName;
  369. List<object> values = new List<object>
  370. {
  371. new EmployeeReference
  372. {
  373. Name = "Bob",
  374. Manager = new EmployeeReference { Name = "Frank" }
  375. },
  376. new Person
  377. {
  378. Department = "Department",
  379. BirthDate = new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc),
  380. LastModified = new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc)
  381. },
  382. "String!",
  383. int.MinValue
  384. };
  385. string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings
  386. {
  387. TypeNameHandling = TypeNameHandling.Objects,
  388. #pragma warning disable 618
  389. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
  390. #pragma warning restore 618
  391. });
  392. StringAssert.AreEqual(@"[
  393. {
  394. ""$id"": ""1"",
  395. ""$type"": """ + employeeRef + @""",
  396. ""Name"": ""Bob"",
  397. ""Manager"": {
  398. ""$id"": ""2"",
  399. ""$type"": """ + employeeRef + @""",
  400. ""Name"": ""Frank"",
  401. ""Manager"": null
  402. }
  403. },
  404. {
  405. ""$type"": """ + personRef + @""",
  406. ""Name"": null,
  407. ""BirthDate"": ""2000-12-30T00:00:00Z"",
  408. ""LastModified"": ""2000-12-30T00:00:00Z""
  409. },
  410. ""String!"",
  411. -2147483648
  412. ]", json);
  413. }
  414. [Test]
  415. public void DeserializeGenericObjectListWithTypeName()
  416. {
  417. string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
  418. string personRef = typeof(Person).AssemblyQualifiedName;
  419. string json = @"[
  420. {
  421. ""$id"": ""1"",
  422. ""$type"": """ + employeeRef + @""",
  423. ""Name"": ""Bob"",
  424. ""Manager"": {
  425. ""$id"": ""2"",
  426. ""$type"": """ + employeeRef + @""",
  427. ""Name"": ""Frank"",
  428. ""Manager"": null
  429. }
  430. },
  431. {
  432. ""$type"": """ + personRef + @""",
  433. ""Name"": null,
  434. ""BirthDate"": ""\/Date(978134400000)\/"",
  435. ""LastModified"": ""\/Date(978134400000)\/""
  436. },
  437. ""String!"",
  438. -2147483648
  439. ]";
  440. List<object> values = (List<object>)JsonConvert.DeserializeObject(json, typeof(List<object>), new JsonSerializerSettings
  441. {
  442. TypeNameHandling = TypeNameHandling.Objects,
  443. #pragma warning disable 618
  444. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
  445. #pragma warning restore 618
  446. });
  447. Assert.AreEqual(4, values.Count);
  448. EmployeeReference e = (EmployeeReference)values[0];
  449. Person p = (Person)values[1];
  450. Assert.AreEqual("Bob", e.Name);
  451. Assert.AreEqual("Frank", e.Manager.Name);
  452. Assert.AreEqual(null, p.Name);
  453. Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.BirthDate);
  454. Assert.AreEqual(new DateTime(2000, 12, 30, 0, 0, 0, DateTimeKind.Utc), p.LastModified);
  455. Assert.AreEqual("String!", values[2]);
  456. Assert.AreEqual((long)int.MinValue, values[3]);
  457. }
  458. [Test]
  459. public void DeserializeWithBadTypeName()
  460. {
  461. string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
  462. string personRef = typeof(Person).AssemblyQualifiedName;
  463. string json = @"{
  464. ""$id"": ""1"",
  465. ""$type"": """ + employeeRef + @""",
  466. ""Name"": ""Name!"",
  467. ""Manager"": null
  468. }";
  469. try
  470. {
  471. JsonConvert.DeserializeObject(json, typeof(Person), new JsonSerializerSettings
  472. {
  473. TypeNameHandling = TypeNameHandling.Objects,
  474. #pragma warning disable 618
  475. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
  476. #pragma warning restore 618
  477. });
  478. }
  479. catch (JsonSerializationException ex)
  480. {
  481. Assert.IsTrue(ex.Message.StartsWith(@"Type specified in JSON '" + employeeRef + @"' is not compatible with '" + personRef + @"'."));
  482. }
  483. }
  484. [Test]
  485. public void DeserializeTypeNameWithNoTypeNameHandling()
  486. {
  487. string employeeRef = typeof(EmployeeReference).AssemblyQualifiedName;
  488. string json = @"{
  489. ""$id"": ""1"",
  490. ""$type"": """ + employeeRef + @""",
  491. ""Name"": ""Name!"",
  492. ""Manager"": null
  493. }";
  494. JObject o = (JObject)JsonConvert.DeserializeObject(json);
  495. StringAssert.AreEqual(@"{
  496. ""Name"": ""Name!"",
  497. ""Manager"": null
  498. }", o.ToString());
  499. }
  500. [Test]
  501. public void DeserializeTypeNameOnly()
  502. {
  503. string json = @"{
  504. ""$id"": ""1"",
  505. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee"",
  506. ""Name"": ""Name!"",
  507. ""Manager"": null
  508. }";
  509. ExceptionAssert.Throws<JsonSerializationException>(() =>
  510. {
  511. JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
  512. {
  513. TypeNameHandling = TypeNameHandling.Objects
  514. });
  515. }, "Type specified in JSON 'Newtonsoft.Json.Tests.TestObjects.Employee' was not resolved. Path '$type', line 3, position 55.");
  516. }
  517. public interface ICorrelatedMessage
  518. {
  519. string CorrelationId { get; set; }
  520. }
  521. public class SendHttpRequest : ICorrelatedMessage
  522. {
  523. public SendHttpRequest()
  524. {
  525. RequestEncoding = "UTF-8";
  526. Method = "GET";
  527. }
  528. public string Method { get; set; }
  529. public Dictionary<string, string> Headers { get; set; }
  530. public string Url { get; set; }
  531. public Dictionary<string, string> RequestData;
  532. public string RequestBodyText { get; set; }
  533. public string User { get; set; }
  534. public string Passwd { get; set; }
  535. public string RequestEncoding { get; set; }
  536. public string CorrelationId { get; set; }
  537. }
  538. [Test]
  539. public void DeserializeGenericTypeName()
  540. {
  541. string typeName = typeof(SendHttpRequest).AssemblyQualifiedName;
  542. string json = @"{
  543. ""$type"": """ + typeName + @""",
  544. ""RequestData"": {
  545. ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"",
  546. ""Id"": ""siedemnaście"",
  547. ""X"": ""323""
  548. },
  549. ""Method"": ""GET"",
  550. ""Url"": ""http://www.onet.pl"",
  551. ""RequestEncoding"": ""UTF-8"",
  552. ""CorrelationId"": ""xyz""
  553. }";
  554. ICorrelatedMessage message = JsonConvert.DeserializeObject<ICorrelatedMessage>(json, new JsonSerializerSettings
  555. {
  556. TypeNameHandling = TypeNameHandling.Objects,
  557. #pragma warning disable 618
  558. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
  559. #pragma warning restore 618
  560. });
  561. CustomAssert.IsInstanceOfType(typeof(SendHttpRequest), message);
  562. SendHttpRequest request = (SendHttpRequest)message;
  563. Assert.AreEqual("xyz", request.CorrelationId);
  564. Assert.AreEqual(2, request.RequestData.Count);
  565. Assert.AreEqual("siedemnaście", request.RequestData["Id"]);
  566. }
  567. [Test]
  568. public void SerializeObjectWithMultipleGenericLists()
  569. {
  570. string containerTypeName = typeof(Container).AssemblyQualifiedName;
  571. string productListTypeName = typeof(List<Product>).AssemblyQualifiedName;
  572. Container container = new Container
  573. {
  574. In = new List<Product>(),
  575. Out = new List<Product>()
  576. };
  577. string json = JsonConvert.SerializeObject(container, Formatting.Indented,
  578. new JsonSerializerSettings
  579. {
  580. NullValueHandling = NullValueHandling.Ignore,
  581. TypeNameHandling = TypeNameHandling.All,
  582. #pragma warning disable 618
  583. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
  584. #pragma warning restore 618
  585. });
  586. StringAssert.AreEqual(@"{
  587. ""$type"": """ + containerTypeName + @""",
  588. ""In"": {
  589. ""$type"": """ + productListTypeName + @""",
  590. ""$values"": []
  591. },
  592. ""Out"": {
  593. ""$type"": """ + productListTypeName + @""",
  594. ""$values"": []
  595. }
  596. }", json);
  597. }
  598. public class TypeNameProperty
  599. {
  600. public string Name { get; set; }
  601. [JsonProperty(TypeNameHandling = TypeNameHandling.All)]
  602. public object Value { get; set; }
  603. }
  604. [Test]
  605. public void WriteObjectTypeNameForProperty()
  606. {
  607. string typeNamePropertyRef = ReflectionUtils.GetTypeName(typeof(TypeNameProperty), TypeNameAssemblyFormatHandling.Simple, null);
  608. TypeNameProperty typeNameProperty = new TypeNameProperty
  609. {
  610. Name = "Name!",
  611. Value = new TypeNameProperty
  612. {
  613. Name = "Nested!"
  614. }
  615. };
  616. string json = JsonConvert.SerializeObject(typeNameProperty, Formatting.Indented);
  617. StringAssert.AreEqual(@"{
  618. ""Name"": ""Name!"",
  619. ""Value"": {
  620. ""$type"": """ + typeNamePropertyRef + @""",
  621. ""Name"": ""Nested!"",
  622. ""Value"": null
  623. }
  624. }", json);
  625. TypeNameProperty deserialized = JsonConvert.DeserializeObject<TypeNameProperty>(json);
  626. Assert.AreEqual("Name!", deserialized.Name);
  627. CustomAssert.IsInstanceOfType(typeof(TypeNameProperty), deserialized.Value);
  628. TypeNameProperty nested = (TypeNameProperty)deserialized.Value;
  629. Assert.AreEqual("Nested!", nested.Name);
  630. Assert.AreEqual(null, nested.Value);
  631. }
  632. [Test]
  633. public void WriteListTypeNameForProperty()
  634. {
  635. string listRef = ReflectionUtils.GetTypeName(typeof(List<int>), TypeNameAssemblyFormatHandling.Simple, null);
  636. TypeNameProperty typeNameProperty = new TypeNameProperty
  637. {
  638. Name = "Name!",
  639. Value = new List<int> { 1, 2, 3, 4, 5 }
  640. };
  641. string json = JsonConvert.SerializeObject(typeNameProperty, Formatting.Indented);
  642. StringAssert.AreEqual(@"{
  643. ""Name"": ""Name!"",
  644. ""Value"": {
  645. ""$type"": """ + listRef + @""",
  646. ""$values"": [
  647. 1,
  648. 2,
  649. 3,
  650. 4,
  651. 5
  652. ]
  653. }
  654. }", json);
  655. TypeNameProperty deserialized = JsonConvert.DeserializeObject<TypeNameProperty>(json);
  656. Assert.AreEqual("Name!", deserialized.Name);
  657. CustomAssert.IsInstanceOfType(typeof(List<int>), deserialized.Value);
  658. List<int> nested = (List<int>)deserialized.Value;
  659. Assert.AreEqual(5, nested.Count);
  660. Assert.AreEqual(1, nested[0]);
  661. Assert.AreEqual(2, nested[1]);
  662. Assert.AreEqual(3, nested[2]);
  663. Assert.AreEqual(4, nested[3]);
  664. Assert.AreEqual(5, nested[4]);
  665. }
  666. [Test]
  667. public void DeserializeUsingCustomBinder()
  668. {
  669. string json = @"{
  670. ""$id"": ""1"",
  671. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Employee"",
  672. ""Name"": ""Name!""
  673. }";
  674. object p = JsonConvert.DeserializeObject(json, null, new JsonSerializerSettings
  675. {
  676. TypeNameHandling = TypeNameHandling.Objects,
  677. #pragma warning disable CS0618 // Type or member is obsolete
  678. Binder = new CustomSerializationBinder()
  679. #pragma warning restore CS0618 // Type or member is obsolete
  680. });
  681. CustomAssert.IsInstanceOfType(typeof(Person), p);
  682. Person person = (Person)p;
  683. Assert.AreEqual("Name!", person.Name);
  684. }
  685. public class CustomSerializationBinder : SerializationBinder
  686. {
  687. public override Type BindToType(string assemblyName, string typeName)
  688. {
  689. return typeof(Person);
  690. }
  691. }
  692. #if !(NET20 || NET35)
  693. [Test]
  694. public void SerializeUsingCustomBinder()
  695. {
  696. TypeNameSerializationBinder binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests");
  697. IList<object> values = new List<object>
  698. {
  699. new Customer
  700. {
  701. Name = "Caroline Customer"
  702. },
  703. new Purchase
  704. {
  705. ProductName = "Elbow Grease",
  706. Price = 5.99m,
  707. Quantity = 1
  708. }
  709. };
  710. string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings
  711. {
  712. TypeNameHandling = TypeNameHandling.Auto,
  713. #pragma warning disable CS0618 // Type or member is obsolete
  714. Binder = binder
  715. #pragma warning restore CS0618 // Type or member is obsolete
  716. });
  717. //[
  718. // {
  719. // "$type": "Customer",
  720. // "Name": "Caroline Customer"
  721. // },
  722. // {
  723. // "$type": "Purchase",
  724. // "ProductName": "Elbow Grease",
  725. // "Price": 5.99,
  726. // "Quantity": 1
  727. // }
  728. //]
  729. StringAssert.AreEqual(@"[
  730. {
  731. ""$type"": ""Customer"",
  732. ""Name"": ""Caroline Customer""
  733. },
  734. {
  735. ""$type"": ""Purchase"",
  736. ""ProductName"": ""Elbow Grease"",
  737. ""Price"": 5.99,
  738. ""Quantity"": 1
  739. }
  740. ]", json);
  741. IList<object> newValues = JsonConvert.DeserializeObject<IList<object>>(json, new JsonSerializerSettings
  742. {
  743. TypeNameHandling = TypeNameHandling.Auto,
  744. #pragma warning disable CS0618 // Type or member is obsolete
  745. Binder = new TypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests")
  746. #pragma warning restore CS0618 // Type or member is obsolete
  747. });
  748. CustomAssert.IsInstanceOfType(typeof(Customer), newValues[0]);
  749. Customer customer = (Customer)newValues[0];
  750. Assert.AreEqual("Caroline Customer", customer.Name);
  751. CustomAssert.IsInstanceOfType(typeof(Purchase), newValues[1]);
  752. Purchase purchase = (Purchase)newValues[1];
  753. Assert.AreEqual("Elbow Grease", purchase.ProductName);
  754. }
  755. public class TypeNameSerializationBinder : SerializationBinder
  756. {
  757. public string TypeFormat { get; private set; }
  758. public TypeNameSerializationBinder(string typeFormat)
  759. {
  760. TypeFormat = typeFormat;
  761. }
  762. public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
  763. {
  764. assemblyName = null;
  765. typeName = serializedType.Name;
  766. }
  767. public override Type BindToType(string assemblyName, string typeName)
  768. {
  769. string resolvedTypeName = string.Format(TypeFormat, typeName);
  770. return Type.GetType(resolvedTypeName, true);
  771. }
  772. }
  773. #endif
  774. [Test]
  775. public void NewSerializeUsingCustomBinder()
  776. {
  777. NewTypeNameSerializationBinder binder = new NewTypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests");
  778. IList<object> values = new List<object>
  779. {
  780. new Customer
  781. {
  782. Name = "Caroline Customer"
  783. },
  784. new Purchase
  785. {
  786. ProductName = "Elbow Grease",
  787. Price = 5.99m,
  788. Quantity = 1
  789. }
  790. };
  791. string json = JsonConvert.SerializeObject(values, Formatting.Indented, new JsonSerializerSettings
  792. {
  793. TypeNameHandling = TypeNameHandling.Auto,
  794. SerializationBinder = binder
  795. });
  796. //[
  797. // {
  798. // "$type": "Customer",
  799. // "Name": "Caroline Customer"
  800. // },
  801. // {
  802. // "$type": "Purchase",
  803. // "ProductName": "Elbow Grease",
  804. // "Price": 5.99,
  805. // "Quantity": 1
  806. // }
  807. //]
  808. StringAssert.AreEqual(@"[
  809. {
  810. ""$type"": ""Customer"",
  811. ""Name"": ""Caroline Customer""
  812. },
  813. {
  814. ""$type"": ""Purchase"",
  815. ""ProductName"": ""Elbow Grease"",
  816. ""Price"": 5.99,
  817. ""Quantity"": 1
  818. }
  819. ]", json);
  820. IList<object> newValues = JsonConvert.DeserializeObject<IList<object>>(json, new JsonSerializerSettings
  821. {
  822. TypeNameHandling = TypeNameHandling.Auto,
  823. SerializationBinder = new NewTypeNameSerializationBinder("Newtonsoft.Json.Tests.Serialization.{0}, Newtonsoft.Json.Tests")
  824. });
  825. CustomAssert.IsInstanceOfType(typeof(Customer), newValues[0]);
  826. Customer customer = (Customer)newValues[0];
  827. Assert.AreEqual("Caroline Customer", customer.Name);
  828. CustomAssert.IsInstanceOfType(typeof(Purchase), newValues[1]);
  829. Purchase purchase = (Purchase)newValues[1];
  830. Assert.AreEqual("Elbow Grease", purchase.ProductName);
  831. }
  832. public class NewTypeNameSerializationBinder : ISerializationBinder
  833. {
  834. public string TypeFormat { get; private set; }
  835. public NewTypeNameSerializationBinder(string typeFormat)
  836. {
  837. TypeFormat = typeFormat;
  838. }
  839. public void BindToName(Type serializedType, out string assemblyName, out string typeName)
  840. {
  841. assemblyName = null;
  842. typeName = serializedType.Name;
  843. }
  844. public Type BindToType(string assemblyName, string typeName)
  845. {
  846. string resolvedTypeName = string.Format(TypeFormat, typeName);
  847. return Type.GetType(resolvedTypeName, true);
  848. }
  849. }
  850. [Test]
  851. public void CollectionWithAbstractItems()
  852. {
  853. HolderClass testObject = new HolderClass();
  854. testObject.TestMember = new ContentSubClass("First One");
  855. testObject.AnotherTestMember = new Dictionary<int, IList<ContentBaseClass>>();
  856. testObject.AnotherTestMember.Add(1, new List<ContentBaseClass>());
  857. testObject.AnotherTestMember[1].Add(new ContentSubClass("Second One"));
  858. testObject.AThirdTestMember = new ContentSubClass("Third One");
  859. JsonSerializer serializingTester = new JsonSerializer();
  860. serializingTester.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  861. StringWriter sw = new StringWriter();
  862. using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
  863. {
  864. jsonWriter.Formatting = Formatting.Indented;
  865. serializingTester.TypeNameHandling = TypeNameHandling.Auto;
  866. serializingTester.Serialize(jsonWriter, testObject);
  867. }
  868. string json = sw.ToString();
  869. string contentSubClassRef = ReflectionUtils.GetTypeName(typeof(ContentSubClass), TypeNameAssemblyFormatHandling.Simple, null);
  870. string dictionaryRef = ReflectionUtils.GetTypeName(typeof(Dictionary<int, IList<ContentBaseClass>>), TypeNameAssemblyFormatHandling.Simple, null);
  871. string listRef = ReflectionUtils.GetTypeName(typeof(List<ContentBaseClass>), TypeNameAssemblyFormatHandling.Simple, null);
  872. string expected = @"{
  873. ""TestMember"": {
  874. ""$type"": """ + contentSubClassRef + @""",
  875. ""SomeString"": ""First One""
  876. },
  877. ""AnotherTestMember"": {
  878. ""$type"": """ + dictionaryRef + @""",
  879. ""1"": [
  880. {
  881. ""$type"": """ + contentSubClassRef + @""",
  882. ""SomeString"": ""Second One""
  883. }
  884. ]
  885. },
  886. ""AThirdTestMember"": {
  887. ""$type"": """ + contentSubClassRef + @""",
  888. ""SomeString"": ""Third One""
  889. }
  890. }";
  891. StringAssert.AreEqual(expected, json);
  892. StringReader sr = new StringReader(json);
  893. JsonSerializer deserializingTester = new JsonSerializer();
  894. HolderClass anotherTestObject;
  895. using (JsonTextReader jsonReader = new JsonTextReader(sr))
  896. {
  897. deserializingTester.TypeNameHandling = TypeNameHandling.Auto;
  898. anotherTestObject = deserializingTester.Deserialize<HolderClass>(jsonReader);
  899. }
  900. Assert.IsNotNull(anotherTestObject);
  901. CustomAssert.IsInstanceOfType(typeof(ContentSubClass), anotherTestObject.TestMember);
  902. CustomAssert.IsInstanceOfType(typeof(Dictionary<int, IList<ContentBaseClass>>), anotherTestObject.AnotherTestMember);
  903. Assert.AreEqual(1, anotherTestObject.AnotherTestMember.Count);
  904. IList<ContentBaseClass> list = anotherTestObject.AnotherTestMember[1];
  905. CustomAssert.IsInstanceOfType(typeof(List<ContentBaseClass>), list);
  906. Assert.AreEqual(1, list.Count);
  907. CustomAssert.IsInstanceOfType(typeof(ContentSubClass), list[0]);
  908. }
  909. [Test]
  910. public void WriteObjectTypeNameForPropertyDemo()
  911. {
  912. Message message = new Message();
  913. message.Address = "http://www.google.com";
  914. message.Body = new SearchDetails
  915. {
  916. Query = "Json.NET",
  917. Language = "en-us"
  918. };
  919. string json = JsonConvert.SerializeObject(message, Formatting.Indented);
  920. // {
  921. // "Address": "http://www.google.com",
  922. // "Body": {
  923. // "$type": "Newtonsoft.Json.Tests.Serialization.SearchDetails, Newtonsoft.Json.Tests",
  924. // "Query": "Json.NET",
  925. // "Language": "en-us"
  926. // }
  927. // }
  928. Message deserialized = JsonConvert.DeserializeObject<Message>(json);
  929. SearchDetails searchDetails = (SearchDetails)deserialized.Body;
  930. // Json.NET
  931. }
  932. public class UrlStatus
  933. {
  934. public int Status { get; set; }
  935. public string Url { get; set; }
  936. }
  937. [Test]
  938. public void GenericDictionaryObject()
  939. {
  940. Dictionary<string, object> collection = new Dictionary<string, object>()
  941. {
  942. { "First", new UrlStatus { Status = 404, Url = @"http://www.bing.com" } },
  943. { "Second", new UrlStatus { Status = 400, Url = @"http://www.google.com" } },
  944. {
  945. "List", new List<UrlStatus>
  946. {
  947. new UrlStatus { Status = 300, Url = @"http://www.yahoo.com" },
  948. new UrlStatus { Status = 200, Url = @"http://www.askjeeves.com" }
  949. }
  950. }
  951. };
  952. string json = JsonConvert.SerializeObject(collection, Formatting.Indented, new JsonSerializerSettings
  953. {
  954. TypeNameHandling = TypeNameHandling.All,
  955. #pragma warning disable 618
  956. TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
  957. #pragma warning restore 618
  958. });
  959. string urlStatusTypeName = ReflectionUtils.GetTypeName(typeof(UrlStatus), TypeNameAssemblyFormatHandling.Simple, null);
  960. StringAssert.AreEqual(@"{
  961. ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"",
  962. ""First"": {
  963. ""$type"": """ + urlStatusTypeName + @""",
  964. ""Status"": 404,
  965. ""Url"": ""http://www.bing.com""
  966. },
  967. ""Second"": {
  968. ""$type"": """ + urlStatusTypeName + @""",
  969. ""Status"": 400,
  970. ""Url"": ""http://www.google.com""
  971. },
  972. ""List"": {
  973. ""$type"": ""System.Collections.Generic.List`1[[" + urlStatusTypeName + @"]], mscorlib"",
  974. ""$values"": [
  975. {
  976. ""$type"": """ + urlStatusTypeName + @""",
  977. ""Status"": 300,
  978. ""Url"": ""http://www.yahoo.com""
  979. },
  980. {
  981. ""$type"": """ + urlStatusTypeName + @""",
  982. ""Status"": 200,
  983. ""Url"": ""http://www.askjeeves.com""
  984. }
  985. ]
  986. }
  987. }", json);
  988. object c = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
  989. {
  990. TypeNameHandling = TypeNameHandling.All,
  991. #pragma warning disable 618
  992. TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
  993. #pragma warning restore 618
  994. });
  995. CustomAssert.IsInstanceOfType(typeof(Dictionary<string, object>), c);
  996. Dictionary<string, object> newCollection = (Dictionary<string, object>)c;
  997. Assert.AreEqual(3, newCollection.Count);
  998. Assert.AreEqual(@"http://www.bing.com", ((UrlStatus)newCollection["First"]).Url);
  999. List<UrlStatus> statues = (List<UrlStatus>)newCollection["List"];
  1000. Assert.AreEqual(2, statues.Count);
  1001. }
  1002. [Test]
  1003. public void SerializingIEnumerableOfTShouldRetainGenericTypeInfo()
  1004. {
  1005. string productClassRef = ReflectionUtils.GetTypeName(typeof(CustomEnumerable<Product>), TypeNameAssemblyFormatHandling.Simple, null);
  1006. CustomEnumerable<Product> products = new CustomEnumerable<Product>();
  1007. string json = JsonConvert.SerializeObject(products, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
  1008. StringAssert.AreEqual(@"{
  1009. ""$type"": """ + productClassRef + @""",
  1010. ""$values"": []
  1011. }", json);
  1012. }
  1013. public class CustomEnumerable<T> : IEnumerable<T>
  1014. {
  1015. //NOTE: a simple linked list
  1016. private readonly T value;
  1017. private readonly CustomEnumerable<T> next;
  1018. private readonly int count;
  1019. private CustomEnumerable(T value, CustomEnumerable<T> next)
  1020. {
  1021. this.value = value;
  1022. this.next = next;
  1023. count = this.next.count + 1;
  1024. }
  1025. public CustomEnumerable()
  1026. {
  1027. count = 0;
  1028. }
  1029. public CustomEnumerable<T> AddFirst(T newVal)
  1030. {
  1031. return new CustomEnumerable<T>(newVal, this);
  1032. }
  1033. public IEnumerator<T> GetEnumerator()
  1034. {
  1035. if (count == 0) // last node
  1036. {
  1037. yield break;
  1038. }
  1039. yield return value;
  1040. var nextInLine = next;
  1041. while (nextInLine != null)
  1042. {
  1043. if (nextInLine.count != 0)
  1044. {
  1045. yield return nextInLine.value;
  1046. }
  1047. nextInLine = nextInLine.next;
  1048. }
  1049. }
  1050. IEnumerator IEnumerable.GetEnumerator()
  1051. {
  1052. return GetEnumerator();
  1053. }
  1054. }
  1055. public class Car
  1056. {
  1057. // included in JSON
  1058. public string Model { get; set; }
  1059. public DateTime Year { get; set; }
  1060. public List<string> Features { get; set; }
  1061. public object[] Objects { get; set; }
  1062. // ignored
  1063. [JsonIgnore]
  1064. public DateTime LastModified { get; set; }
  1065. }
  1066. [Test]
  1067. public void ByteArrays()
  1068. {
  1069. Car testerObject = new Car();
  1070. testerObject.Year = new DateTime(2000, 10, 5, 1, 1, 1, DateTimeKind.Utc);
  1071. byte[] data = new byte[] { 75, 65, 82, 73, 82, 65 };
  1072. testerObject.Objects = new object[] { data, "prueba" };
  1073. JsonSerializerSettings jsonSettings = new JsonSerializerSettings();
  1074. jsonSettings.NullValueHandling = NullValueHandling.Ignore;
  1075. jsonSettings.TypeNameHandling = TypeNameHandling.All;
  1076. string output = JsonConvert.SerializeObject(testerObject, Formatting.Indented, jsonSettings);
  1077. string carClassRef = ReflectionUtils.GetTypeName(typeof(Car), TypeNameAssemblyFormatHandling.Simple, null);
  1078. StringAssert.AreEqual(output, @"{
  1079. ""$type"": """ + carClassRef + @""",
  1080. ""Year"": ""2000-10-05T01:01:01Z"",
  1081. ""Objects"": {
  1082. ""$type"": ""System.Object[], mscorlib"",
  1083. ""$values"": [
  1084. {
  1085. ""$type"": ""System.Byte[], mscorlib"",
  1086. ""$value"": ""S0FSSVJB""
  1087. },
  1088. ""prueba""
  1089. ]
  1090. }
  1091. }");
  1092. Car obj = JsonConvert.DeserializeObject<Car>(output, jsonSettings);
  1093. Assert.IsNotNull(obj);
  1094. Assert.IsTrue(obj.Objects[0] is byte[]);
  1095. byte[] d = (byte[])obj.Objects[0];
  1096. CollectionAssert.AreEquivalent(data, d);
  1097. }
  1098. #if !(DNXCORE50)
  1099. [Test]
  1100. public void ISerializableTypeNameHandlingTest()
  1101. {
  1102. //Create an instance of our example type
  1103. IExample e = new Example("Rob");
  1104. SerializableWrapper w = new SerializableWrapper
  1105. {
  1106. Content = e
  1107. };
  1108. //Test Binary Serialization Round Trip
  1109. //This will work find because the Binary Formatter serializes type names
  1110. //this.TestBinarySerializationRoundTrip(e);
  1111. //Test Json Serialization
  1112. //This fails because the JsonSerializer doesn't serialize type names correctly for ISerializable objects
  1113. //Type Names should be serialized for All, Auto and Object modes
  1114. TestJsonSerializationRoundTrip(w, TypeNameHandling.All);
  1115. TestJsonSerializationRoundTrip(w, TypeNameHandling.Auto);
  1116. TestJsonSerializationRoundTrip(w, TypeNameHandling.Objects);
  1117. }
  1118. private void TestJsonSerializationRoundTrip(SerializableWrapper e, TypeNameHandling flag)
  1119. {
  1120. StringWriter writer = new StringWriter();
  1121. //Create our serializer and set Type Name Handling appropriately
  1122. JsonSerializer serializer = new JsonSerializer();
  1123. serializer.TypeNameHandling = flag;
  1124. //Do the actual serialization and dump to Console for inspection
  1125. serializer.Serialize(new JsonTextWriter(writer), e);
  1126. //Now try to deserialize
  1127. //Json.Net will cause an error here as it will try and instantiate
  1128. //the interface directly because it failed to respect the
  1129. //TypeNameHandling property on serialization
  1130. SerializableWrapper f = serializer.Deserialize<SerializableWrapper>(new JsonTextReader(new StringReader(writer.ToString())));
  1131. //Check Round Trip
  1132. Assert.AreEqual(e, f, "Objects should be equal after round trip json serialization");
  1133. }
  1134. #endif
  1135. #if !(NET20 || NET35)
  1136. [Test]
  1137. public void SerializationBinderWithFullName()
  1138. {
  1139. Message message = new Message
  1140. {
  1141. Address = "jamesnk@testtown.com",
  1142. Body = new Version(1, 2, 3, 4)
  1143. };
  1144. string json = JsonConvert.SerializeObject(message, Formatting.Indented, new JsonSerializerSettings
  1145. {
  1146. TypeNameHandling = TypeNameHandling.All,
  1147. #pragma warning disable CS0618 // Type or member is obsolete
  1148. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full,
  1149. Binder = new MetroBinder(),
  1150. #pragma warning restore CS0618 // Type or member is obsolete
  1151. ContractResolver = new DefaultContractResolver
  1152. {
  1153. #if !(PORTABLE || DNXCORE50)
  1154. IgnoreSerializableAttribute = true
  1155. #endif
  1156. }
  1157. });
  1158. StringAssert.AreEqual(@"{
  1159. ""$type"": "":::MESSAGE:::, AssemblyName"",
  1160. ""Address"": ""jamesnk@testtown.com"",
  1161. ""Body"": {
  1162. ""$type"": "":::VERSION:::, AssemblyName"",
  1163. ""Major"": 1,
  1164. ""Minor"": 2,
  1165. ""Build"": 3,
  1166. ""Revision"": 4,
  1167. ""MajorRevision"": 0,
  1168. ""MinorRevision"": 4
  1169. }
  1170. }", json);
  1171. }
  1172. public class MetroBinder : SerializationBinder
  1173. {
  1174. public override Type BindToType(string assemblyName, string typeName)
  1175. {
  1176. return null;
  1177. }
  1178. public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
  1179. {
  1180. assemblyName = "AssemblyName";
  1181. #if !(DNXCORE50)
  1182. typeName = ":::" + serializedType.Name.ToUpper(CultureInfo.InvariantCulture) + ":::";
  1183. #else
  1184. typeName = ":::" + serializedType.Name.ToUpper() + ":::";
  1185. #endif
  1186. }
  1187. }
  1188. #endif
  1189. [Test]
  1190. public void TypeNameIntList()
  1191. {
  1192. TypeNameList<int> l = new TypeNameList<int>();
  1193. l.Add(1);
  1194. l.Add(2);
  1195. l.Add(3);
  1196. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  1197. StringAssert.AreEqual(@"[
  1198. 1,
  1199. 2,
  1200. 3
  1201. ]", json);
  1202. }
  1203. [Test]
  1204. public void TypeNameComponentList()
  1205. {
  1206. var c1 = new TestComponentSimple();
  1207. TypeNameList<object> l = new TypeNameList<object>();
  1208. l.Add(c1);
  1209. l.Add(new Employee
  1210. {
  1211. BirthDate = new DateTime(2000, 12, 12, 12, 12, 12, DateTimeKind.Utc),
  1212. Department = "Department!"
  1213. });
  1214. l.Add("String!");
  1215. l.Add(long.MaxValue);
  1216. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  1217. StringAssert.AreEqual(@"[
  1218. {
  1219. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1220. ""MyProperty"": 0
  1221. },
  1222. {
  1223. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Organization.Employee, Newtonsoft.Json.Tests"",
  1224. ""FirstName"": null,
  1225. ""LastName"": null,
  1226. ""BirthDate"": ""2000-12-12T12:12:12Z"",
  1227. ""Department"": ""Department!"",
  1228. ""JobTitle"": null
  1229. },
  1230. ""String!"",
  1231. 9223372036854775807
  1232. ]", json);
  1233. TypeNameList<object> l2 = JsonConvert.DeserializeObject<TypeNameList<object>>(json);
  1234. Assert.AreEqual(4, l2.Count);
  1235. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), l2[0]);
  1236. CustomAssert.IsInstanceOfType(typeof(Employee), l2[1]);
  1237. CustomAssert.IsInstanceOfType(typeof(string), l2[2]);
  1238. CustomAssert.IsInstanceOfType(typeof(long), l2[3]);
  1239. }
  1240. [Test]
  1241. public void TypeNameDictionary()
  1242. {
  1243. TypeNameDictionary<object> l = new TypeNameDictionary<object>();
  1244. l.Add("First", new TestComponentSimple { MyProperty = 1 });
  1245. l.Add("Second", "String!");
  1246. l.Add("Third", long.MaxValue);
  1247. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  1248. StringAssert.AreEqual(@"{
  1249. ""First"": {
  1250. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1251. ""MyProperty"": 1
  1252. },
  1253. ""Second"": ""String!"",
  1254. ""Third"": 9223372036854775807
  1255. }", json);
  1256. TypeNameDictionary<object> l2 = JsonConvert.DeserializeObject<TypeNameDictionary<object>>(json);
  1257. Assert.AreEqual(3, l2.Count);
  1258. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), l2["First"]);
  1259. Assert.AreEqual(1, ((TestComponentSimple)l2["First"]).MyProperty);
  1260. CustomAssert.IsInstanceOfType(typeof(string), l2["Second"]);
  1261. CustomAssert.IsInstanceOfType(typeof(long), l2["Third"]);
  1262. }
  1263. [Test]
  1264. public void TypeNameObjectItems()
  1265. {
  1266. TypeNameObject o1 = new TypeNameObject();
  1267. o1.Object1 = new TestComponentSimple { MyProperty = 1 };
  1268. o1.Object2 = 123;
  1269. o1.ObjectNotHandled = new TestComponentSimple { MyProperty = int.MaxValue };
  1270. o1.String = "String!";
  1271. o1.Integer = int.MaxValue;
  1272. string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
  1273. string expected = @"{
  1274. ""Object1"": {
  1275. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1276. ""MyProperty"": 1
  1277. },
  1278. ""Object2"": 123,
  1279. ""ObjectNotHandled"": {
  1280. ""MyProperty"": 2147483647
  1281. },
  1282. ""String"": ""String!"",
  1283. ""Integer"": 2147483647
  1284. }";
  1285. StringAssert.AreEqual(expected, json);
  1286. TypeNameObject o2 = JsonConvert.DeserializeObject<TypeNameObject>(json);
  1287. Assert.IsNotNull(o2);
  1288. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), o2.Object1);
  1289. Assert.AreEqual(1, ((TestComponentSimple)o2.Object1).MyProperty);
  1290. CustomAssert.IsInstanceOfType(typeof(long), o2.Object2);
  1291. CustomAssert.IsInstanceOfType(typeof(JObject), o2.ObjectNotHandled);
  1292. StringAssert.AreEqual(@"{
  1293. ""MyProperty"": 2147483647
  1294. }", o2.ObjectNotHandled.ToString());
  1295. }
  1296. [Test]
  1297. public void PropertyItemTypeNameHandling()
  1298. {
  1299. PropertyItemTypeNameHandling c1 = new PropertyItemTypeNameHandling();
  1300. c1.Data = new List<object>
  1301. {
  1302. 1,
  1303. "two",
  1304. new TestComponentSimple { MyProperty = 1 }
  1305. };
  1306. string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
  1307. StringAssert.AreEqual(@"{
  1308. ""Data"": [
  1309. 1,
  1310. ""two"",
  1311. {
  1312. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1313. ""MyProperty"": 1
  1314. }
  1315. ]
  1316. }", json);
  1317. PropertyItemTypeNameHandling c2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandling>(json);
  1318. Assert.AreEqual(3, c2.Data.Count);
  1319. CustomAssert.IsInstanceOfType(typeof(long), c2.Data[0]);
  1320. CustomAssert.IsInstanceOfType(typeof(string), c2.Data[1]);
  1321. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), c2.Data[2]);
  1322. TestComponentSimple c = (TestComponentSimple)c2.Data[2];
  1323. Assert.AreEqual(1, c.MyProperty);
  1324. }
  1325. [Test]
  1326. public void PropertyItemTypeNameHandlingNestedCollections()
  1327. {
  1328. PropertyItemTypeNameHandling c1 = new PropertyItemTypeNameHandling
  1329. {
  1330. Data = new List<object>
  1331. {
  1332. new TestComponentSimple { MyProperty = 1 },
  1333. new List<object>
  1334. {
  1335. new List<object>
  1336. {
  1337. new List<object>()
  1338. }
  1339. }
  1340. }
  1341. };
  1342. string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
  1343. StringAssert.AreEqual(@"{
  1344. ""Data"": [
  1345. {
  1346. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1347. ""MyProperty"": 1
  1348. },
  1349. {
  1350. ""$type"": ""System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib"",
  1351. ""$values"": [
  1352. [
  1353. []
  1354. ]
  1355. ]
  1356. }
  1357. ]
  1358. }", json);
  1359. PropertyItemTypeNameHandling c2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandling>(json);
  1360. Assert.AreEqual(2, c2.Data.Count);
  1361. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), c2.Data[0]);
  1362. CustomAssert.IsInstanceOfType(typeof(List<object>), c2.Data[1]);
  1363. List<object> c = (List<object>)c2.Data[1];
  1364. CustomAssert.IsInstanceOfType(typeof(JArray), c[0]);
  1365. json = @"{
  1366. ""Data"": [
  1367. {
  1368. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1369. ""MyProperty"": 1
  1370. },
  1371. {
  1372. ""$type"": ""System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib"",
  1373. ""$values"": [
  1374. {
  1375. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1376. ""MyProperty"": 1
  1377. }
  1378. ]
  1379. }
  1380. ]
  1381. }";
  1382. c2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandling>(json);
  1383. Assert.AreEqual(2, c2.Data.Count);
  1384. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), c2.Data[0]);
  1385. CustomAssert.IsInstanceOfType(typeof(List<object>), c2.Data[1]);
  1386. c = (List<object>)c2.Data[1];
  1387. CustomAssert.IsInstanceOfType(typeof(JObject), c[0]);
  1388. JObject o = (JObject)c[0];
  1389. Assert.AreEqual(1, (int)o["MyProperty"]);
  1390. }
  1391. [Test]
  1392. public void PropertyItemTypeNameHandlingNestedDictionaries()
  1393. {
  1394. PropertyItemTypeNameHandlingDictionary c1 = new PropertyItemTypeNameHandlingDictionary()
  1395. {
  1396. Data = new Dictionary<string, object>
  1397. {
  1398. {
  1399. "one", new TestComponentSimple { MyProperty = 1 }
  1400. },
  1401. {
  1402. "two", new Dictionary<string, object>
  1403. {
  1404. {
  1405. "one", new Dictionary<string, object>
  1406. {
  1407. { "one", 1 }
  1408. }
  1409. }
  1410. }
  1411. }
  1412. }
  1413. };
  1414. string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
  1415. StringAssert.AreEqual(@"{
  1416. ""Data"": {
  1417. ""one"": {
  1418. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1419. ""MyProperty"": 1
  1420. },
  1421. ""two"": {
  1422. ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"",
  1423. ""one"": {
  1424. ""one"": 1
  1425. }
  1426. }
  1427. }
  1428. }", json);
  1429. PropertyItemTypeNameHandlingDictionary c2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandlingDictionary>(json);
  1430. Assert.AreEqual(2, c2.Data.Count);
  1431. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), c2.Data["one"]);
  1432. CustomAssert.IsInstanceOfType(typeof(Dictionary<string, object>), c2.Data["two"]);
  1433. Dictionary<string, object> c = (Dictionary<string, object>)c2.Data["two"];
  1434. CustomAssert.IsInstanceOfType(typeof(JObject), c["one"]);
  1435. json = @"{
  1436. ""Data"": {
  1437. ""one"": {
  1438. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1439. ""MyProperty"": 1
  1440. },
  1441. ""two"": {
  1442. ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"",
  1443. ""one"": {
  1444. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1445. ""MyProperty"": 1
  1446. }
  1447. }
  1448. }
  1449. }";
  1450. c2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandlingDictionary>(json);
  1451. Assert.AreEqual(2, c2.Data.Count);
  1452. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), c2.Data["one"]);
  1453. CustomAssert.IsInstanceOfType(typeof(Dictionary<string, object>), c2.Data["two"]);
  1454. c = (Dictionary<string, object>)c2.Data["two"];
  1455. CustomAssert.IsInstanceOfType(typeof(JObject), c["one"]);
  1456. JObject o = (JObject)c["one"];
  1457. Assert.AreEqual(1, (int)o["MyProperty"]);
  1458. }
  1459. [Test]
  1460. public void PropertyItemTypeNameHandlingObject()
  1461. {
  1462. PropertyItemTypeNameHandlingObject o1 = new PropertyItemTypeNameHandlingObject
  1463. {
  1464. Data = new TypeNameHandlingTestObject
  1465. {
  1466. Prop1 = new List<object>
  1467. {
  1468. new TestComponentSimple
  1469. {
  1470. MyProperty = 1
  1471. }
  1472. },
  1473. Prop2 = new TestComponentSimple
  1474. {
  1475. MyProperty = 1
  1476. },
  1477. Prop3 = 3,
  1478. Prop4 = new JObject()
  1479. }
  1480. };
  1481. string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
  1482. StringAssert.AreEqual(@"{
  1483. ""Data"": {
  1484. ""Prop1"": {
  1485. ""$type"": ""System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib"",
  1486. ""$values"": [
  1487. {
  1488. ""MyProperty"": 1
  1489. }
  1490. ]
  1491. },
  1492. ""Prop2"": {
  1493. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1494. ""MyProperty"": 1
  1495. },
  1496. ""Prop3"": 3,
  1497. ""Prop4"": {}
  1498. }
  1499. }", json);
  1500. PropertyItemTypeNameHandlingObject o2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandlingObject>(json);
  1501. Assert.IsNotNull(o2);
  1502. Assert.IsNotNull(o2.Data);
  1503. CustomAssert.IsInstanceOfType(typeof(List<object>), o2.Data.Prop1);
  1504. CustomAssert.IsInstanceOfType(typeof(TestComponentSimple), o2.Data.Prop2);
  1505. CustomAssert.IsInstanceOfType(typeof(long), o2.Data.Prop3);
  1506. CustomAssert.IsInstanceOfType(typeof(JObject), o2.Data.Prop4);
  1507. List<object> o = (List<object>)o2.Data.Prop1;
  1508. JObject j = (JObject)o[0];
  1509. Assert.AreEqual(1, (int)j["MyProperty"]);
  1510. }
  1511. #if !(NET35 || NET20 || PORTABLE40)
  1512. [Test]
  1513. public void PropertyItemTypeNameHandlingDynamic()
  1514. {
  1515. PropertyItemTypeNameHandlingDynamic d1 = new PropertyItemTypeNameHandlingDynamic();
  1516. dynamic data = new DynamicDictionary();
  1517. data.one = new TestComponentSimple
  1518. {
  1519. MyProperty = 1
  1520. };
  1521. dynamic data2 = new DynamicDictionary();
  1522. data2.one = new TestComponentSimple
  1523. {
  1524. MyProperty = 2
  1525. };
  1526. data.two = data2;
  1527. d1.Data = (DynamicDictionary)data;
  1528. string json = JsonConvert.SerializeObject(d1, Formatting.Indented);
  1529. StringAssert.AreEqual(@"{
  1530. ""Data"": {
  1531. ""one"": {
  1532. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1533. ""MyProperty"": 1
  1534. },
  1535. ""two"": {
  1536. ""$type"": ""Newtonsoft.Json.Tests.Linq.DynamicDictionary, Newtonsoft.Json.Tests"",
  1537. ""one"": {
  1538. ""MyProperty"": 2
  1539. }
  1540. }
  1541. }
  1542. }", json);
  1543. PropertyItemTypeNameHandlingDynamic d2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandlingDynamic>(json);
  1544. Assert.IsNotNull(d2);
  1545. Assert.IsNotNull(d2.Data);
  1546. dynamic data3 = d2.Data;
  1547. TestComponentSimple c = (TestComponentSimple)data3.one;
  1548. Assert.AreEqual(1, c.MyProperty);
  1549. dynamic data4 = data3.two;
  1550. JObject o = (JObject)data4.one;
  1551. Assert.AreEqual(2, (int)o["MyProperty"]);
  1552. json = @"{
  1553. ""Data"": {
  1554. ""one"": {
  1555. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1556. ""MyProperty"": 1
  1557. },
  1558. ""two"": {
  1559. ""$type"": ""Newtonsoft.Json.Tests.Linq.DynamicDictionary, Newtonsoft.Json.Tests"",
  1560. ""one"": {
  1561. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.TestComponentSimple, Newtonsoft.Json.Tests"",
  1562. ""MyProperty"": 2
  1563. }
  1564. }
  1565. }
  1566. }";
  1567. d2 = JsonConvert.DeserializeObject<PropertyItemTypeNameHandlingDynamic>(json);
  1568. data3 = d2.Data;
  1569. data4 = data3.two;
  1570. o = (JObject)data4.one;
  1571. Assert.AreEqual(2, (int)o["MyProperty"]);
  1572. }
  1573. #endif
  1574. #if !(DNXCORE50)
  1575. [Test]
  1576. public void SerializeDeserialize_DictionaryContextContainsGuid_DeserializesItemAsGuid()
  1577. {
  1578. const string contextKey = "k1";
  1579. var someValue = new Guid("a6e986df-fc2c-4906-a1ef-9492388f7833");
  1580. Dictionary<string, Guid> inputContext = new Dictionary<string, Guid>();
  1581. inputContext.Add(contextKey, someValue);
  1582. JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings()
  1583. {
  1584. Formatting = Formatting.Indented,
  1585. TypeNameHandling = TypeNameHandling.All
  1586. };
  1587. string serializedString = JsonConvert.SerializeObject(inputContext, jsonSerializerSettings);
  1588. StringAssert.AreEqual(@"{
  1589. ""$type"": ""System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Guid, mscorlib]], mscorlib"",
  1590. ""k1"": ""a6e986df-fc2c-4906-a1ef-9492388f7833""
  1591. }", serializedString);
  1592. var deserializedObject = (Dictionary<string, Guid>)JsonConvert.DeserializeObject(serializedString, jsonSerializerSettings);
  1593. Assert.AreEqual(someValue, deserializedObject[contextKey]);
  1594. }
  1595. [Test]
  1596. public void TypeNameHandlingWithISerializableValues()
  1597. {
  1598. MyParent p = new MyParent
  1599. {
  1600. Child = new MyChild
  1601. {
  1602. MyProperty = "string!"
  1603. }
  1604. };
  1605. JsonSerializerSettings settings = new JsonSerializerSettings
  1606. {
  1607. TypeNameHandling = TypeNameHandling.Auto,
  1608. DateFormatHandling = DateFormatHandling.IsoDateFormat,
  1609. MissingMemberHandling = MissingMemberHandling.Ignore,
  1610. DefaultValueHandling = DefaultValueHandling.Ignore,
  1611. NullValueHandling = NullValueHandling.Ignore,
  1612. Formatting = Formatting.Indented
  1613. };
  1614. string json = JsonConvert.SerializeObject(p, settings);
  1615. StringAssert.AreEqual(@"{
  1616. ""c"": {
  1617. ""$type"": ""Newtonsoft.Json.Tests.Serialization.MyChild, Newtonsoft.Json.Tests"",
  1618. ""p"": ""string!""
  1619. }
  1620. }", json);
  1621. MyParent p2 = JsonConvert.DeserializeObject<MyParent>(json, settings);
  1622. CustomAssert.IsInstanceOfType(typeof(MyChild), p2.Child);
  1623. Assert.AreEqual("string!", ((MyChild)p2.Child).MyProperty);
  1624. }
  1625. [Test]
  1626. public void TypeNameHandlingWithISerializableValuesAndArray()
  1627. {
  1628. MyParent p = new MyParent
  1629. {
  1630. Child = new MyChildList
  1631. {
  1632. "string!"
  1633. }
  1634. };
  1635. JsonSerializerSettings settings = new JsonSerializerSettings
  1636. {
  1637. TypeNameHandling = TypeNameHandling.Auto,
  1638. DateFormatHandling = DateFormatHandling.IsoDateFormat,
  1639. MissingMemberHandling = MissingMemberHandling.Ignore,
  1640. DefaultValueHandling = DefaultValueHandling.Ignore,
  1641. NullValueHandling = NullValueHandling.Ignore,
  1642. Formatting = Formatting.Indented
  1643. };
  1644. string json = JsonConvert.SerializeObject(p, settings);
  1645. StringAssert.AreEqual(@"{
  1646. ""c"": {
  1647. ""$type"": ""Newtonsoft.Json.Tests.Serialization.MyChildList, Newtonsoft.Json.Tests"",
  1648. ""$values"": [
  1649. ""string!""
  1650. ]
  1651. }
  1652. }", json);
  1653. MyParent p2 = JsonConvert.DeserializeObject<MyParent>(json, settings);
  1654. CustomAssert.IsInstanceOfType(typeof(MyChildList), p2.Child);
  1655. Assert.AreEqual(1, ((MyChildList)p2.Child).Count);
  1656. Assert.AreEqual("string!", ((MyChildList)p2.Child)[0]);
  1657. }
  1658. [Test]
  1659. public void ParentTypeNameHandlingWithISerializableValues()
  1660. {
  1661. ParentParent pp = new ParentParent();
  1662. pp.ParentProp = new MyParent
  1663. {
  1664. Child = new MyChild
  1665. {
  1666. MyProperty = "string!"
  1667. }
  1668. };
  1669. JsonSerializerSettings settings = new JsonSerializerSettings
  1670. {
  1671. DateFormatHandling = DateFormatHandling.IsoDateFormat,
  1672. MissingMemberHandling = MissingMemberHandling.Ignore,
  1673. DefaultValueHandling = DefaultValueHandling.Ignore,
  1674. NullValueHandling = NullValueHandling.Ignore,
  1675. Formatting = Formatting.Indented
  1676. };
  1677. string json = JsonConvert.SerializeObject(pp, settings);
  1678. StringAssert.AreEqual(@"{
  1679. ""ParentProp"": {
  1680. ""c"": {
  1681. ""$type"": ""Newtonsoft.Json.Tests.Serialization.MyChild, Newtonsoft.Json.Tests"",
  1682. ""p"": ""string!""
  1683. }
  1684. }
  1685. }", json);
  1686. ParentParent pp2 = JsonConvert.DeserializeObject<ParentParent>(json, settings);
  1687. MyParent p2 = pp2.ParentProp;
  1688. CustomAssert.IsInstanceOfType(typeof(MyChild), p2.Child);
  1689. Assert.AreEqual("string!", ((MyChild)p2.Child).MyProperty);
  1690. }
  1691. #endif
  1692. [Test]
  1693. public void ListOfStackWithFullAssemblyName()
  1694. {
  1695. var input = new List<Stack<string>>();
  1696. input.Add(new Stack<string>(new List<string> { "One", "Two", "Three" }));
  1697. input.Add(new Stack<string>(new List<string> { "Four", "Five", "Six" }));
  1698. input.Add(new Stack<string>(new List<string> { "Seven", "Eight", "Nine" }));
  1699. string serialized = JsonConvert.SerializeObject(input,
  1700. Newtonsoft.Json.Formatting.Indented,
  1701. new JsonSerializerSettings
  1702. {
  1703. TypeNameHandling = TypeNameHandling.All,
  1704. #pragma warning disable 618
  1705. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full // TypeNameHandling.Auto will work
  1706. #pragma warning restore 618
  1707. });
  1708. var output = JsonConvert.DeserializeObject<List<Stack<string>>>(serialized,
  1709. new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
  1710. );
  1711. List<string> strings = output.SelectMany(s => s).ToList();
  1712. Assert.AreEqual(9, strings.Count);
  1713. Assert.AreEqual("One", strings[0]);
  1714. Assert.AreEqual("Nine", strings[8]);
  1715. }
  1716. #if !NET20
  1717. [Test]
  1718. public void ExistingBaseValue()
  1719. {
  1720. string json = @"{
  1721. ""itemIdentifier"": {
  1722. ""$type"": ""Newtonsoft.Json.Tests.Serialization.ReportItemKeys, Newtonsoft.Json.Tests"",
  1723. ""dataType"": 0,
  1724. ""wantedUnitID"": 1,
  1725. ""application"": 3,
  1726. ""id"": 101,
  1727. ""name"": ""Machine""
  1728. },
  1729. ""isBusinessEntity"": false,
  1730. ""isKeyItem"": true,
  1731. ""summarizeOnThisItem"": false
  1732. }";
  1733. GroupingInfo g = JsonConvert.DeserializeObject<GroupingInfo>(json, new JsonSerializerSettings
  1734. {
  1735. TypeNameHandling = TypeNameHandling.Objects
  1736. });
  1737. ReportItemKeys item = (ReportItemKeys)g.ItemIdentifier;
  1738. Assert.AreEqual(1UL, item.WantedUnitID);
  1739. }
  1740. #endif
  1741. #if !(NET20 || NET35)
  1742. [Test]
  1743. public void GenericItemTypeCollection()
  1744. {
  1745. DataType data = new DataType();
  1746. data.Rows.Add("key", new List<MyInterfaceImplementationType> { new MyInterfaceImplementationType() { SomeProperty = "property" } });
  1747. string serialized = JsonConvert.SerializeObject(data, Formatting.Indented);
  1748. StringAssert.AreEqual(@"{
  1749. ""Rows"": {
  1750. ""key"": {
  1751. ""$type"": ""System.Collections.Generic.List`1[[Newtonsoft.Json.Tests.Serialization.MyInterfaceImplementationType, Newtonsoft.Json.Tests]], mscorlib"",
  1752. ""$values"": [
  1753. {
  1754. ""SomeProperty"": ""property""
  1755. }
  1756. ]
  1757. }
  1758. }
  1759. }", serialized);
  1760. DataType deserialized = JsonConvert.DeserializeObject<DataType>(serialized);
  1761. Assert.AreEqual("property", deserialized.Rows["key"].First().SomeProperty);
  1762. }
  1763. #endif
  1764. #if !(NET20 || PORTABLE || PORTABLE40)
  1765. [Test]
  1766. public void DeserializeComplexGenericDictionary_Simple()
  1767. {
  1768. JsonSerializerSettings serializerSettings = new JsonSerializerSettings
  1769. {
  1770. TypeNameHandling = TypeNameHandling.All,
  1771. #pragma warning disable 618
  1772. TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
  1773. #pragma warning restore 618
  1774. };
  1775. Dictionary<int, HashSet<string>> dictionary = new Dictionary<int, HashSet<string>>
  1776. {
  1777. { 1, new HashSet<string>(new[] { "test" }) },
  1778. };
  1779. string obtainedJson = JsonConvert.SerializeObject(dictionary, serializerSettings);
  1780. Dictionary<int, HashSet<string>> obtainedDictionary = (Dictionary<int, HashSet<string>>)JsonConvert.DeserializeObject(obtainedJson, serializerSettings);
  1781. Assert.IsNotNull(obtainedDictionary);
  1782. }
  1783. [Test]
  1784. public void DeserializeComplexGenericDictionary_Full()
  1785. {
  1786. JsonSerializerSettings serializerSettings = new JsonSerializerSettings
  1787. {
  1788. TypeNameHandling = TypeNameHandling.All,
  1789. #pragma warning disable 618
  1790. TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
  1791. #pragma warning restore 618
  1792. };
  1793. Dictionary<int, HashSet<string>> dictionary = new Dictionary<int, HashSet<string>>
  1794. {
  1795. { 1, new HashSet<string>(new[] { "test" }) },
  1796. };
  1797. string obtainedJson = JsonConvert.SerializeObject(dictionary, serializerSettings);
  1798. Dictionary<int, HashSet<string>> obtainedDictionary = (Dictionary<int, HashSet<string>>)JsonConvert.DeserializeObject(obtainedJson, serializerSettings);
  1799. Assert.IsNotNull(obtainedDictionary);
  1800. }
  1801. [Test]
  1802. public void SerializeNullableStructProperty_Auto()
  1803. {
  1804. JsonSerializerSettings serializerSettings = new JsonSerializerSettings
  1805. {
  1806. TypeNameHandling = TypeNameHandling.Auto,
  1807. Formatting = Formatting.Indented
  1808. };
  1809. ObjectWithOptionalMessage objWithMessage = new ObjectWithOptionalMessage(new Message2("Hello!"));
  1810. string json = JsonConvert.SerializeObject(objWithMessage, serializerSettings);
  1811. StringAssert.AreEqual(@"{
  1812. ""Message"": {
  1813. ""Value"": ""Hello!""
  1814. }
  1815. }", json);
  1816. }
  1817. [Test]
  1818. public void DeserializeNullableStructProperty_Auto()
  1819. {
  1820. JsonSerializerSettings serializerSettings = new JsonSerializerSettings
  1821. {
  1822. TypeNameHandling = TypeNameHandling.Auto,
  1823. Formatting = Formatting.Indented
  1824. };
  1825. string json = @"{
  1826. ""Message"": {
  1827. ""Value"": ""Hello!""
  1828. }
  1829. }";
  1830. ObjectWithOptionalMessage objWithMessage = JsonConvert.DeserializeObject<ObjectWithOptionalMessage>(json, serializerSettings);
  1831. StringAssert.AreEqual("Hello!", objWithMessage.Message.Value.Value);
  1832. }
  1833. #endif
  1834. }
  1835. public struct Message2
  1836. {
  1837. public string Value { get; }
  1838. [JsonConstructor]
  1839. public Message2(string value)
  1840. {
  1841. if (value == null) throw new ArgumentNullException(nameof(value));
  1842. Value = value;
  1843. }
  1844. }
  1845. public class ObjectWithOptionalMessage
  1846. {
  1847. public Message2? Message { get; }
  1848. public ObjectWithOptionalMessage(Message2? message)
  1849. {
  1850. Message = message;
  1851. }
  1852. }
  1853. public class DataType
  1854. {
  1855. public DataType()
  1856. {
  1857. Rows = new Dictionary<string, IEnumerable<IMyInterfaceType>>();
  1858. }
  1859. [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto)]
  1860. public Dictionary<string, IEnumerable<IMyInterfaceType>> Rows { get; private set; }
  1861. }
  1862. public interface IMyInterfaceType
  1863. {
  1864. string SomeProperty { get; set; }
  1865. }
  1866. public class MyInterfaceImplementationType : IMyInterfaceType
  1867. {
  1868. public string SomeProperty { get; set; }
  1869. }
  1870. #if !(DNXCORE50)
  1871. public class ParentParent
  1872. {
  1873. [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
  1874. public MyParent ParentProp { get; set; }
  1875. }
  1876. [Serializable]
  1877. public class MyParent : ISerializable
  1878. {
  1879. public ISomeBase Child { get; internal set; }
  1880. public MyParent(SerializationInfo info, StreamingContext context)
  1881. {
  1882. Child = (ISomeBase)info.GetValue("c", typeof(ISomeBase));
  1883. }
  1884. public MyParent()
  1885. {
  1886. }
  1887. void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  1888. {
  1889. info.AddValue("c", Child);
  1890. }
  1891. }
  1892. public class MyChild : ISomeBase
  1893. {
  1894. [JsonProperty("p")]
  1895. public String MyProperty { get; internal set; }
  1896. }
  1897. public class MyChildList : List<string>, ISomeBase
  1898. {
  1899. }
  1900. public interface ISomeBase
  1901. {
  1902. }
  1903. #endif
  1904. public class Message
  1905. {
  1906. public string Address { get; set; }
  1907. [JsonProperty(TypeNameHandling = TypeNameHandling.All)]
  1908. public object Body { get; set; }
  1909. }
  1910. public class SearchDetails
  1911. {
  1912. public string Query { get; set; }
  1913. public string Language { get; set; }
  1914. }
  1915. public class Customer
  1916. {
  1917. public string Name { get; set; }
  1918. }
  1919. public class Purchase
  1920. {
  1921. public string ProductName { get; set; }
  1922. public decimal Price { get; set; }
  1923. public int Quantity { get; set; }
  1924. }
  1925. #if !(DNXCORE50)
  1926. public class SerializableWrapper
  1927. {
  1928. public object Content { get; set; }
  1929. public override bool Equals(object obj)
  1930. {
  1931. SerializableWrapper w = obj as SerializableWrapper;
  1932. if (w == null)
  1933. {
  1934. return false;
  1935. }
  1936. return Equals(w.Content, Content);
  1937. }
  1938. public override int GetHashCode()
  1939. {
  1940. if (Content == null)
  1941. {
  1942. return 0;
  1943. }
  1944. return Content.GetHashCode();
  1945. }
  1946. }
  1947. public interface IExample
  1948. : ISerializable
  1949. {
  1950. String Name { get; }
  1951. }
  1952. [Serializable]
  1953. public class Example
  1954. : IExample
  1955. {
  1956. public Example(String name)
  1957. {
  1958. Name = name;
  1959. }
  1960. protected Example(SerializationInfo info, StreamingContext context)
  1961. {
  1962. Name = info.GetString("name");
  1963. }
  1964. public void GetObjectData(SerializationInfo info, StreamingContext context)
  1965. {
  1966. info.AddValue("name", Name);
  1967. }
  1968. public String Name { get; set; }
  1969. public override bool Equals(object obj)
  1970. {
  1971. if (obj == null)
  1972. {
  1973. return false;
  1974. }
  1975. if (ReferenceEquals(this, obj))
  1976. {
  1977. return true;
  1978. }
  1979. if (obj is IExample)
  1980. {
  1981. return Name.Equals(((IExample)obj).Name);
  1982. }
  1983. else
  1984. {
  1985. return false;
  1986. }
  1987. }
  1988. public override int GetHashCode()
  1989. {
  1990. if (Name == null)
  1991. {
  1992. return 0;
  1993. }
  1994. return Name.GetHashCode();
  1995. }
  1996. }
  1997. #endif
  1998. public class PropertyItemTypeNameHandlingObject
  1999. {
  2000. [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)]
  2001. public TypeNameHandlingTestObject Data { get; set; }
  2002. }
  2003. #if !(NET35 || NET20 || PORTABLE40)
  2004. public class PropertyItemTypeNameHandlingDynamic
  2005. {
  2006. [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)]
  2007. public DynamicDictionary Data { get; set; }
  2008. }
  2009. #endif
  2010. public class TypeNameHandlingTestObject
  2011. {
  2012. public object Prop1 { get; set; }
  2013. public object Prop2 { get; set; }
  2014. public object Prop3 { get; set; }
  2015. public object Prop4 { get; set; }
  2016. }
  2017. public class PropertyItemTypeNameHandlingDictionary
  2018. {
  2019. [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)]
  2020. public IDictionary<string, object> Data { get; set; }
  2021. }
  2022. public class PropertyItemTypeNameHandling
  2023. {
  2024. [JsonProperty(ItemTypeNameHandling = TypeNameHandling.All)]
  2025. public IList<object> Data { get; set; }
  2026. }
  2027. [JsonArray(ItemTypeNameHandling = TypeNameHandling.All)]
  2028. public class TypeNameList<T> : List<T>
  2029. {
  2030. }
  2031. [JsonDictionary(ItemTypeNameHandling = TypeNameHandling.All)]
  2032. public class TypeNameDictionary<T> : Dictionary<string, T>
  2033. {
  2034. }
  2035. [JsonObject(ItemTypeNameHandling = TypeNameHandling.All)]
  2036. public class TypeNameObject
  2037. {
  2038. public object Object1 { get; set; }
  2039. public object Object2 { get; set; }
  2040. [JsonProperty(TypeNameHandling = TypeNameHandling.None)]
  2041. public object ObjectNotHandled { get; set; }
  2042. public string String { get; set; }
  2043. public int Integer { get; set; }
  2044. }
  2045. #if !NET20
  2046. [DataContract]
  2047. public class GroupingInfo
  2048. {
  2049. [DataMember]
  2050. public ApplicationItemKeys ItemIdentifier { get; set; }
  2051. public GroupingInfo()
  2052. {
  2053. ItemIdentifier = new ApplicationItemKeys();
  2054. }
  2055. }
  2056. [DataContract]
  2057. public class ApplicationItemKeys
  2058. {
  2059. [DataMember]
  2060. public int ID { get; set; }
  2061. [DataMember]
  2062. public string Name { get; set; }
  2063. }
  2064. [DataContract]
  2065. public class ReportItemKeys : ApplicationItemKeys
  2066. {
  2067. protected ulong _wantedUnit;
  2068. [DataMember]
  2069. public ulong WantedUnitID
  2070. {
  2071. get { return _wantedUnit; }
  2072. set { _wantedUnit = value; }
  2073. }
  2074. }
  2075. #endif
  2076. }
  2077. #endif