PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Json45r7/Source/Src/Newtonsoft.Json.Tests/Serialization/PreserveReferencesHandlingTests.cs

https://bitbucket.org/wantstudios/bitbucketclient
C# | 1099 lines | 905 code | 145 blank | 49 comment | 3 complexity | 6d28b70d12c6f9ef27f1a75860e5b98e 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. using System;
  26. using System.Collections.Generic;
  27. using System.IO;
  28. using System.Text;
  29. using Newtonsoft.Json.Linq;
  30. using Newtonsoft.Json.Tests.TestObjects;
  31. #if !NETFX_CORE
  32. using NUnit.Framework;
  33. #else
  34. using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
  35. using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
  36. using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
  37. #endif
  38. namespace Newtonsoft.Json.Tests.Serialization
  39. {
  40. [TestFixture]
  41. public class PreserveReferencesHandlingTests : TestFixtureBase
  42. {
  43. [Test]
  44. public void SerializeDictionarysWithPreserveObjectReferences()
  45. {
  46. CircularDictionary circularDictionary = new CircularDictionary();
  47. circularDictionary.Add("other", new CircularDictionary { { "blah", null } });
  48. circularDictionary.Add("self", circularDictionary);
  49. string json = JsonConvert.SerializeObject(circularDictionary, Formatting.Indented,
  50. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });
  51. Assert.AreEqual(@"{
  52. ""$id"": ""1"",
  53. ""other"": {
  54. ""$id"": ""2"",
  55. ""blah"": null
  56. },
  57. ""self"": {
  58. ""$ref"": ""1""
  59. }
  60. }", json);
  61. }
  62. [Test]
  63. public void DeserializeDictionarysWithPreserveObjectReferences()
  64. {
  65. string json = @"{
  66. ""$id"": ""1"",
  67. ""other"": {
  68. ""$id"": ""2"",
  69. ""blah"": null
  70. },
  71. ""self"": {
  72. ""$ref"": ""1""
  73. }
  74. }";
  75. CircularDictionary circularDictionary = JsonConvert.DeserializeObject<CircularDictionary>(json,
  76. new JsonSerializerSettings
  77. {
  78. PreserveReferencesHandling = PreserveReferencesHandling.All
  79. });
  80. Assert.AreEqual(2, circularDictionary.Count);
  81. Assert.AreEqual(1, circularDictionary["other"].Count);
  82. Assert.AreEqual(circularDictionary, circularDictionary["self"]);
  83. }
  84. public class CircularList : List<CircularList>
  85. {
  86. }
  87. [Test]
  88. public void SerializeCircularListsError()
  89. {
  90. string classRef = typeof(CircularList).FullName;
  91. CircularList circularList = new CircularList();
  92. circularList.Add(null);
  93. circularList.Add(new CircularList { null });
  94. circularList.Add(new CircularList { new CircularList { circularList } });
  95. ExceptionAssert.Throws<JsonSerializationException>(
  96. "Self referencing loop detected with type '" + classRef + "'. Path '[2][0]'.",
  97. () =>
  98. {
  99. JsonConvert.SerializeObject(circularList, Formatting.Indented);
  100. });
  101. }
  102. [Test]
  103. public void SerializeCircularListsIgnore()
  104. {
  105. CircularList circularList = new CircularList();
  106. circularList.Add(null);
  107. circularList.Add(new CircularList { null });
  108. circularList.Add(new CircularList { new CircularList { circularList } });
  109. string json = JsonConvert.SerializeObject(circularList,
  110. Formatting.Indented,
  111. new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
  112. Assert.AreEqual(@"[
  113. null,
  114. [
  115. null
  116. ],
  117. [
  118. []
  119. ]
  120. ]", json);
  121. }
  122. [Test]
  123. public void SerializeListsWithPreserveObjectReferences()
  124. {
  125. CircularList circularList = new CircularList();
  126. circularList.Add(null);
  127. circularList.Add(new CircularList { null });
  128. circularList.Add(new CircularList { new CircularList { circularList } });
  129. string json = JsonConvert.SerializeObject(circularList, Formatting.Indented,
  130. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });
  131. Assert.AreEqual(@"{
  132. ""$id"": ""1"",
  133. ""$values"": [
  134. null,
  135. {
  136. ""$id"": ""2"",
  137. ""$values"": [
  138. null
  139. ]
  140. },
  141. {
  142. ""$id"": ""3"",
  143. ""$values"": [
  144. {
  145. ""$id"": ""4"",
  146. ""$values"": [
  147. {
  148. ""$ref"": ""1""
  149. }
  150. ]
  151. }
  152. ]
  153. }
  154. ]
  155. }", json);
  156. }
  157. [Test]
  158. public void DeserializeListsWithPreserveObjectReferences()
  159. {
  160. string json = @"{
  161. ""$id"": ""1"",
  162. ""$values"": [
  163. null,
  164. {
  165. ""$id"": ""2"",
  166. ""$values"": [
  167. null
  168. ]
  169. },
  170. {
  171. ""$id"": ""3"",
  172. ""$values"": [
  173. {
  174. ""$id"": ""4"",
  175. ""$values"": [
  176. {
  177. ""$ref"": ""1""
  178. }
  179. ]
  180. }
  181. ]
  182. }
  183. ]
  184. }";
  185. CircularList circularList = JsonConvert.DeserializeObject<CircularList>(json,
  186. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });
  187. Assert.AreEqual(3, circularList.Count);
  188. Assert.AreEqual(null, circularList[0]);
  189. Assert.AreEqual(1, circularList[1].Count);
  190. Assert.AreEqual(1, circularList[2].Count);
  191. Assert.AreEqual(1, circularList[2][0].Count);
  192. Assert.IsTrue(ReferenceEquals(circularList, circularList[2][0][0]));
  193. }
  194. [Test]
  195. public void DeserializeArraysWithPreserveObjectReferences()
  196. {
  197. string json = @"{
  198. ""$id"": ""1"",
  199. ""$values"": [
  200. null,
  201. {
  202. ""$id"": ""2"",
  203. ""$values"": [
  204. null
  205. ]
  206. },
  207. {
  208. ""$id"": ""3"",
  209. ""$values"": [
  210. {
  211. ""$id"": ""4"",
  212. ""$values"": [
  213. {
  214. ""$ref"": ""1""
  215. }
  216. ]
  217. }
  218. ]
  219. }
  220. ]
  221. }";
  222. ExceptionAssert.Throws<JsonSerializationException>(
  223. @"Cannot preserve reference to array or readonly list: System.String[][]. Path '$values', line 3, position 15.",
  224. () =>
  225. {
  226. JsonConvert.DeserializeObject<string[][]>(json,
  227. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });
  228. });
  229. }
  230. public class CircularDictionary : Dictionary<string, CircularDictionary>
  231. {
  232. }
  233. [Test]
  234. public void SerializeCircularDictionarysError()
  235. {
  236. string classRef = typeof(CircularDictionary).FullName;
  237. CircularDictionary circularDictionary = new CircularDictionary();
  238. circularDictionary.Add("other", new CircularDictionary {{"blah", null}});
  239. circularDictionary.Add("self", circularDictionary);
  240. ExceptionAssert.Throws<JsonSerializationException>(
  241. @"Self referencing loop detected with type '" + classRef + "'. Path ''.",
  242. () =>
  243. {
  244. JsonConvert.SerializeObject(circularDictionary, Formatting.Indented);
  245. });
  246. }
  247. [Test]
  248. public void SerializeCircularDictionarysIgnore()
  249. {
  250. CircularDictionary circularDictionary = new CircularDictionary();
  251. circularDictionary.Add("other", new CircularDictionary { { "blah", null } });
  252. circularDictionary.Add("self", circularDictionary);
  253. string json = JsonConvert.SerializeObject(circularDictionary, Formatting.Indented,
  254. new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
  255. Assert.AreEqual(@"{
  256. ""other"": {
  257. ""blah"": null
  258. }
  259. }", json);
  260. }
  261. [Test]
  262. public void UnexpectedEnd()
  263. {
  264. string json = @"{
  265. ""$id"":";
  266. ExceptionAssert.Throws<JsonSerializationException>(
  267. @"Unexpected end when deserializing object. Path '$id', line 2, position 9.",
  268. () =>
  269. {
  270. JsonConvert.DeserializeObject<string[][]>(json,
  271. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });
  272. });
  273. }
  274. public class CircularReferenceClassConverter : JsonConverter
  275. {
  276. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  277. {
  278. CircularReferenceClass circularReferenceClass = (CircularReferenceClass)value;
  279. string reference = serializer.ReferenceResolver.GetReference(serializer, circularReferenceClass);
  280. JObject me = new JObject();
  281. me["$id"] = new JValue(reference);
  282. me["$type"] = new JValue(value.GetType().Name);
  283. me["Name"] = new JValue(circularReferenceClass.Name);
  284. JObject o = JObject.FromObject(circularReferenceClass.Child, serializer);
  285. me["Child"] = o;
  286. me.WriteTo(writer);
  287. }
  288. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  289. {
  290. JObject o = JObject.Load(reader);
  291. string id = (string)o["$id"];
  292. if (id != null)
  293. {
  294. CircularReferenceClass circularReferenceClass = new CircularReferenceClass();
  295. serializer.Populate(o.CreateReader(), circularReferenceClass);
  296. return circularReferenceClass;
  297. }
  298. else
  299. {
  300. string reference = (string)o["$ref"];
  301. return serializer.ReferenceResolver.ResolveReference(serializer, reference);
  302. }
  303. }
  304. public override bool CanConvert(Type objectType)
  305. {
  306. return (objectType == typeof(CircularReferenceClass));
  307. }
  308. }
  309. [Test]
  310. public void SerializeCircularReferencesWithConverter()
  311. {
  312. CircularReferenceClass c1 = new CircularReferenceClass { Name = "c1" };
  313. CircularReferenceClass c2 = new CircularReferenceClass { Name = "c2" };
  314. CircularReferenceClass c3 = new CircularReferenceClass { Name = "c3" };
  315. c1.Child = c2;
  316. c2.Child = c3;
  317. c3.Child = c1;
  318. string json = JsonConvert.SerializeObject(c1, Formatting.Indented, new JsonSerializerSettings
  319. {
  320. PreserveReferencesHandling = PreserveReferencesHandling.Objects,
  321. Converters = new List<JsonConverter> { new CircularReferenceClassConverter() }
  322. });
  323. Assert.AreEqual(@"{
  324. ""$id"": ""1"",
  325. ""$type"": ""CircularReferenceClass"",
  326. ""Name"": ""c1"",
  327. ""Child"": {
  328. ""$id"": ""2"",
  329. ""$type"": ""CircularReferenceClass"",
  330. ""Name"": ""c2"",
  331. ""Child"": {
  332. ""$id"": ""3"",
  333. ""$type"": ""CircularReferenceClass"",
  334. ""Name"": ""c3"",
  335. ""Child"": {
  336. ""$ref"": ""1""
  337. }
  338. }
  339. }
  340. }", json);
  341. }
  342. [Test]
  343. public void DeserializeCircularReferencesWithConverter()
  344. {
  345. string json = @"{
  346. ""$id"": ""1"",
  347. ""$type"": ""CircularReferenceClass"",
  348. ""Name"": ""c1"",
  349. ""Child"": {
  350. ""$id"": ""2"",
  351. ""$type"": ""CircularReferenceClass"",
  352. ""Name"": ""c2"",
  353. ""Child"": {
  354. ""$id"": ""3"",
  355. ""$type"": ""CircularReferenceClass"",
  356. ""Name"": ""c3"",
  357. ""Child"": {
  358. ""$ref"": ""1""
  359. }
  360. }
  361. }
  362. }";
  363. CircularReferenceClass c1 = JsonConvert.DeserializeObject<CircularReferenceClass>(json, new JsonSerializerSettings
  364. {
  365. PreserveReferencesHandling = PreserveReferencesHandling.Objects,
  366. Converters = new List<JsonConverter> { new CircularReferenceClassConverter() }
  367. });
  368. Assert.AreEqual("c1", c1.Name);
  369. Assert.AreEqual("c2", c1.Child.Name);
  370. Assert.AreEqual("c3", c1.Child.Child.Name);
  371. Assert.AreEqual("c1", c1.Child.Child.Child.Name);
  372. }
  373. [Test]
  374. public void SerializeEmployeeReference()
  375. {
  376. EmployeeReference mikeManager = new EmployeeReference
  377. {
  378. Name = "Mike Manager"
  379. };
  380. EmployeeReference joeUser = new EmployeeReference
  381. {
  382. Name = "Joe User",
  383. Manager = mikeManager
  384. };
  385. List<EmployeeReference> employees = new List<EmployeeReference>
  386. {
  387. mikeManager,
  388. joeUser
  389. };
  390. string json = JsonConvert.SerializeObject(employees, Formatting.Indented);
  391. Assert.AreEqual(@"[
  392. {
  393. ""$id"": ""1"",
  394. ""Name"": ""Mike Manager"",
  395. ""Manager"": null
  396. },
  397. {
  398. ""$id"": ""2"",
  399. ""Name"": ""Joe User"",
  400. ""Manager"": {
  401. ""$ref"": ""1""
  402. }
  403. }
  404. ]", json);
  405. }
  406. [Test]
  407. public void DeserializeEmployeeReference()
  408. {
  409. string json = @"[
  410. {
  411. ""$id"": ""1"",
  412. ""Name"": ""Mike Manager"",
  413. ""Manager"": null
  414. },
  415. {
  416. ""$id"": ""2"",
  417. ""Name"": ""Joe User"",
  418. ""Manager"": {
  419. ""$ref"": ""1""
  420. }
  421. }
  422. ]";
  423. List<EmployeeReference> employees = JsonConvert.DeserializeObject<List<EmployeeReference>>(json);
  424. Assert.AreEqual(2, employees.Count);
  425. Assert.AreEqual("Mike Manager", employees[0].Name);
  426. Assert.AreEqual("Joe User", employees[1].Name);
  427. Assert.AreEqual(employees[0], employees[1].Manager);
  428. }
  429. [Test]
  430. public void SerializeCircularReference()
  431. {
  432. CircularReferenceClass c1 = new CircularReferenceClass { Name = "c1" };
  433. CircularReferenceClass c2 = new CircularReferenceClass { Name = "c2" };
  434. CircularReferenceClass c3 = new CircularReferenceClass { Name = "c3" };
  435. c1.Child = c2;
  436. c2.Child = c3;
  437. c3.Child = c1;
  438. string json = JsonConvert.SerializeObject(c1, Formatting.Indented, new JsonSerializerSettings
  439. {
  440. PreserveReferencesHandling = PreserveReferencesHandling.Objects
  441. });
  442. Assert.AreEqual(@"{
  443. ""$id"": ""1"",
  444. ""Name"": ""c1"",
  445. ""Child"": {
  446. ""$id"": ""2"",
  447. ""Name"": ""c2"",
  448. ""Child"": {
  449. ""$id"": ""3"",
  450. ""Name"": ""c3"",
  451. ""Child"": {
  452. ""$ref"": ""1""
  453. }
  454. }
  455. }
  456. }", json);
  457. }
  458. [Test]
  459. public void DeserializeCircularReference()
  460. {
  461. string json = @"{
  462. ""$id"": ""1"",
  463. ""Name"": ""c1"",
  464. ""Child"": {
  465. ""$id"": ""2"",
  466. ""Name"": ""c2"",
  467. ""Child"": {
  468. ""$id"": ""3"",
  469. ""Name"": ""c3"",
  470. ""Child"": {
  471. ""$ref"": ""1""
  472. }
  473. }
  474. }
  475. }";
  476. CircularReferenceClass c1 =
  477. JsonConvert.DeserializeObject<CircularReferenceClass>(json, new JsonSerializerSettings
  478. {
  479. PreserveReferencesHandling = PreserveReferencesHandling.Objects
  480. });
  481. Assert.AreEqual("c1", c1.Name);
  482. Assert.AreEqual("c2", c1.Child.Name);
  483. Assert.AreEqual("c3", c1.Child.Child.Name);
  484. Assert.AreEqual("c1", c1.Child.Child.Child.Name);
  485. }
  486. [Test]
  487. public void SerializeReferenceInList()
  488. {
  489. EmployeeReference e1 = new EmployeeReference { Name = "e1" };
  490. EmployeeReference e2 = new EmployeeReference { Name = "e2" };
  491. List<EmployeeReference> employees = new List<EmployeeReference> { e1, e2, e1, e2 };
  492. string json = JsonConvert.SerializeObject(employees, Formatting.Indented);
  493. Assert.AreEqual(@"[
  494. {
  495. ""$id"": ""1"",
  496. ""Name"": ""e1"",
  497. ""Manager"": null
  498. },
  499. {
  500. ""$id"": ""2"",
  501. ""Name"": ""e2"",
  502. ""Manager"": null
  503. },
  504. {
  505. ""$ref"": ""1""
  506. },
  507. {
  508. ""$ref"": ""2""
  509. }
  510. ]", json);
  511. }
  512. [Test]
  513. public void DeserializeReferenceInList()
  514. {
  515. string json = @"[
  516. {
  517. ""$id"": ""1"",
  518. ""Name"": ""e1"",
  519. ""Manager"": null
  520. },
  521. {
  522. ""$id"": ""2"",
  523. ""Name"": ""e2"",
  524. ""Manager"": null
  525. },
  526. {
  527. ""$ref"": ""1""
  528. },
  529. {
  530. ""$ref"": ""2""
  531. }
  532. ]";
  533. List<EmployeeReference> employees = JsonConvert.DeserializeObject<List<EmployeeReference>>(json);
  534. Assert.AreEqual(4, employees.Count);
  535. Assert.AreEqual("e1", employees[0].Name);
  536. Assert.AreEqual("e2", employees[1].Name);
  537. Assert.AreEqual("e1", employees[2].Name);
  538. Assert.AreEqual("e2", employees[3].Name);
  539. Assert.AreEqual(employees[0], employees[2]);
  540. Assert.AreEqual(employees[1], employees[3]);
  541. }
  542. [Test]
  543. public void SerializeReferenceInDictionary()
  544. {
  545. EmployeeReference e1 = new EmployeeReference { Name = "e1" };
  546. EmployeeReference e2 = new EmployeeReference { Name = "e2" };
  547. Dictionary<string, EmployeeReference> employees = new Dictionary<string, EmployeeReference>
  548. {
  549. {"One", e1},
  550. {"Two", e2},
  551. {"Three", e1},
  552. {"Four", e2}
  553. };
  554. string json = JsonConvert.SerializeObject(employees, Formatting.Indented);
  555. Assert.AreEqual(@"{
  556. ""One"": {
  557. ""$id"": ""1"",
  558. ""Name"": ""e1"",
  559. ""Manager"": null
  560. },
  561. ""Two"": {
  562. ""$id"": ""2"",
  563. ""Name"": ""e2"",
  564. ""Manager"": null
  565. },
  566. ""Three"": {
  567. ""$ref"": ""1""
  568. },
  569. ""Four"": {
  570. ""$ref"": ""2""
  571. }
  572. }", json);
  573. }
  574. [Test]
  575. public void DeserializeReferenceInDictionary()
  576. {
  577. string json = @"{
  578. ""One"": {
  579. ""$id"": ""1"",
  580. ""Name"": ""e1"",
  581. ""Manager"": null
  582. },
  583. ""Two"": {
  584. ""$id"": ""2"",
  585. ""Name"": ""e2"",
  586. ""Manager"": null
  587. },
  588. ""Three"": {
  589. ""$ref"": ""1""
  590. },
  591. ""Four"": {
  592. ""$ref"": ""2""
  593. }
  594. }";
  595. Dictionary<string, EmployeeReference> employees = JsonConvert.DeserializeObject<Dictionary<string, EmployeeReference>>(json);
  596. Assert.AreEqual(4, employees.Count);
  597. EmployeeReference e1 = employees["One"];
  598. EmployeeReference e2 = employees["Two"];
  599. Assert.AreEqual("e1", e1.Name);
  600. Assert.AreEqual("e2", e2.Name);
  601. Assert.AreEqual(e1, employees["Three"]);
  602. Assert.AreEqual(e2, employees["Four"]);
  603. }
  604. [Test]
  605. public void ExampleWithout()
  606. {
  607. Person p = new Person
  608. {
  609. BirthDate = new DateTime(1980, 12, 23, 0, 0, 0, DateTimeKind.Utc),
  610. LastModified = new DateTime(2009, 2, 20, 12, 59, 21, DateTimeKind.Utc),
  611. Department = "IT",
  612. Name = "James"
  613. };
  614. List<Person> people = new List<Person>();
  615. people.Add(p);
  616. people.Add(p);
  617. string json = JsonConvert.SerializeObject(people, Formatting.Indented);
  618. //[
  619. // {
  620. // "Name": "James",
  621. // "BirthDate": "\/Date(346377600000)\/",
  622. // "LastModified": "\/Date(1235134761000)\/"
  623. // },
  624. // {
  625. // "Name": "James",
  626. // "BirthDate": "\/Date(346377600000)\/",
  627. // "LastModified": "\/Date(1235134761000)\/"
  628. // }
  629. //]
  630. }
  631. [Test]
  632. public void ExampleWith()
  633. {
  634. Person p = new Person
  635. {
  636. BirthDate = new DateTime(1980, 12, 23, 0, 0, 0, DateTimeKind.Utc),
  637. LastModified = new DateTime(2009, 2, 20, 12, 59, 21, DateTimeKind.Utc),
  638. Department = "IT",
  639. Name = "James"
  640. };
  641. List<Person> people = new List<Person>();
  642. people.Add(p);
  643. people.Add(p);
  644. string json = JsonConvert.SerializeObject(people, Formatting.Indented,
  645. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
  646. //[
  647. // {
  648. // "$id": "1",
  649. // "Name": "James",
  650. // "BirthDate": "\/Date(346377600000)\/",
  651. // "LastModified": "\/Date(1235134761000)\/"
  652. // },
  653. // {
  654. // "$ref": "1"
  655. // }
  656. //]
  657. List<Person> deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json,
  658. new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
  659. Console.WriteLine(deserializedPeople.Count);
  660. // 2
  661. Person p1 = deserializedPeople[0];
  662. Person p2 = deserializedPeople[1];
  663. Console.WriteLine(p1.Name);
  664. // James
  665. Console.WriteLine(p2.Name);
  666. // James
  667. bool equal = Object.ReferenceEquals(p1, p2);
  668. // true
  669. }
  670. [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
  671. public class User
  672. {
  673. #region properties
  674. [JsonProperty(Required = Required.Always, PropertyName = "SecretType")]
  675. private string secretType;
  676. [JsonProperty(Required = Required.Always)]
  677. public string Login { get; set; }
  678. public Type SecretType
  679. {
  680. get { return Type.GetType(secretType); }
  681. set { secretType = value.AssemblyQualifiedName; }
  682. }
  683. [JsonProperty]
  684. public User Friend { get; set; }
  685. #endregion
  686. #region constructors
  687. public User()
  688. {
  689. }
  690. public User(string login, Type secretType)
  691. : this()
  692. {
  693. this.Login = login;
  694. this.SecretType = secretType;
  695. }
  696. #endregion
  697. #region methods
  698. public override int GetHashCode()
  699. {
  700. return SecretType.GetHashCode();
  701. }
  702. public override string ToString()
  703. {
  704. return string.Format("SecretType: {0}, Login: {1}", secretType, Login);
  705. }
  706. #endregion
  707. }
  708. [Test]
  709. public void DeserializeTypeWithDubiousGetHashcode()
  710. {
  711. User user1 = new User("Peter", typeof(Version));
  712. User user2 = new User("Michael", typeof(Version));
  713. user1.Friend = user2;
  714. JsonSerializerSettings serializerSettings = new JsonSerializerSettings
  715. {
  716. TypeNameHandling = TypeNameHandling.All,
  717. ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
  718. ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
  719. PreserveReferencesHandling = PreserveReferencesHandling.Objects
  720. };
  721. string json = JsonConvert.SerializeObject(user1, Formatting.Indented, serializerSettings);
  722. User deserializedUser = JsonConvert.DeserializeObject<User>(json, serializerSettings);
  723. Assert.IsNotNull(deserializedUser);
  724. }
  725. [Test]
  726. public void PreserveReferencesHandlingWithReusedJsonSerializer()
  727. {
  728. MyClass c = new MyClass();
  729. IList<MyClass> myClasses1 = new List<MyClass>
  730. {
  731. c,
  732. c
  733. };
  734. var ser = new JsonSerializer()
  735. {
  736. PreserveReferencesHandling = PreserveReferencesHandling.All
  737. };
  738. MemoryStream ms = new MemoryStream();
  739. using (var sw = new StreamWriter(ms))
  740. using (var writer = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
  741. {
  742. ser.Serialize(writer, myClasses1);
  743. }
  744. byte[] data = ms.ToArray();
  745. string json = Encoding.UTF8.GetString(data, 0, data.Length);
  746. Assert.AreEqual(@"{
  747. ""$id"": ""1"",
  748. ""$values"": [
  749. {
  750. ""$id"": ""2"",
  751. ""PreProperty"": 0,
  752. ""PostProperty"": 0
  753. },
  754. {
  755. ""$ref"": ""2""
  756. }
  757. ]
  758. }", json);
  759. ms = new MemoryStream(data);
  760. IList<MyClass> myClasses2;
  761. using (var sr = new StreamReader(ms))
  762. using (var reader = new JsonTextReader(sr))
  763. {
  764. myClasses2 = ser.Deserialize<IList<MyClass>>(reader);
  765. }
  766. Assert.AreEqual(2, myClasses2.Count);
  767. Assert.AreEqual(myClasses2[0], myClasses2[1]);
  768. Assert.AreNotEqual(myClasses1[0], myClasses2[0]);
  769. }
  770. [Test]
  771. public void ReferencedIntList()
  772. {
  773. ReferencedList<int> l = new ReferencedList<int>();
  774. l.Add(1);
  775. l.Add(2);
  776. l.Add(3);
  777. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  778. Assert.AreEqual(@"[
  779. 1,
  780. 2,
  781. 3
  782. ]", json);
  783. }
  784. [Test]
  785. public void ReferencedComponentList()
  786. {
  787. var c1 = new TestComponentSimple();
  788. ReferencedList<TestComponentSimple> l = new ReferencedList<TestComponentSimple>();
  789. l.Add(c1);
  790. l.Add(new TestComponentSimple());
  791. l.Add(c1);
  792. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  793. Assert.AreEqual(@"[
  794. {
  795. ""$id"": ""1"",
  796. ""MyProperty"": 0
  797. },
  798. {
  799. ""$id"": ""2"",
  800. ""MyProperty"": 0
  801. },
  802. {
  803. ""$ref"": ""1""
  804. }
  805. ]", json);
  806. }
  807. [Test]
  808. public void ReferencedIntDictionary()
  809. {
  810. ReferencedDictionary<int> l = new ReferencedDictionary<int>();
  811. l.Add("First", 1);
  812. l.Add("Second", 2);
  813. l.Add("Third", 3);
  814. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  815. Assert.AreEqual(@"{
  816. ""First"": 1,
  817. ""Second"": 2,
  818. ""Third"": 3
  819. }", json);
  820. }
  821. [Test]
  822. public void ReferencedComponentDictionary()
  823. {
  824. var c1 = new TestComponentSimple();
  825. ReferencedDictionary<TestComponentSimple> l = new ReferencedDictionary<TestComponentSimple>();
  826. l.Add("First", c1);
  827. l.Add("Second", new TestComponentSimple());
  828. l.Add("Third", c1);
  829. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  830. Assert.AreEqual(@"{
  831. ""First"": {
  832. ""$id"": ""1"",
  833. ""MyProperty"": 0
  834. },
  835. ""Second"": {
  836. ""$id"": ""2"",
  837. ""MyProperty"": 0
  838. },
  839. ""Third"": {
  840. ""$ref"": ""1""
  841. }
  842. }", json);
  843. ReferencedDictionary<TestComponentSimple> d = JsonConvert.DeserializeObject<ReferencedDictionary<TestComponentSimple>>(json);
  844. Assert.AreEqual(3, d.Count);
  845. Assert.IsTrue(ReferenceEquals(d["First"], d["Third"]));
  846. }
  847. [Test]
  848. public void ReferencedObjectItems()
  849. {
  850. ReferenceObject o1 = new ReferenceObject();
  851. o1.Component1 = new TestComponentSimple { MyProperty = 1 };
  852. o1.Component2 = o1.Component1;
  853. o1.ComponentNotReference = new TestComponentSimple();
  854. o1.String = "String!";
  855. o1.Integer = int.MaxValue;
  856. string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
  857. string expected = @"{
  858. ""Component1"": {
  859. ""$id"": ""1"",
  860. ""MyProperty"": 1
  861. },
  862. ""Component2"": {
  863. ""$ref"": ""1""
  864. },
  865. ""ComponentNotReference"": {
  866. ""MyProperty"": 0
  867. },
  868. ""String"": ""String!"",
  869. ""Integer"": 2147483647
  870. }";
  871. Assert.AreEqual(expected, json);
  872. ReferenceObject referenceObject = JsonConvert.DeserializeObject<ReferenceObject>(json);
  873. Assert.IsNotNull(referenceObject);
  874. Assert.IsTrue(ReferenceEquals(referenceObject.Component1, referenceObject.Component2));
  875. }
  876. [Test]
  877. public void PropertyItemIsReferenceObject()
  878. {
  879. TestComponentSimple c1 = new TestComponentSimple();
  880. PropertyItemIsReferenceObject o1 = new PropertyItemIsReferenceObject
  881. {
  882. Data = new PropertyItemIsReferenceBody
  883. {
  884. Prop1 = c1,
  885. Prop2 = c1,
  886. Data = new List<TestComponentSimple>
  887. {
  888. c1
  889. }
  890. }
  891. };
  892. string json = JsonConvert.SerializeObject(o1, Formatting.Indented);
  893. Assert.AreEqual(@"{
  894. ""Data"": {
  895. ""Prop1"": {
  896. ""$id"": ""1"",
  897. ""MyProperty"": 0
  898. },
  899. ""Prop2"": {
  900. ""$ref"": ""1""
  901. },
  902. ""Data"": {
  903. ""$id"": ""2"",
  904. ""$values"": [
  905. {
  906. ""MyProperty"": 0
  907. }
  908. ]
  909. }
  910. }
  911. }", json);
  912. PropertyItemIsReferenceObject o2 = JsonConvert.DeserializeObject<PropertyItemIsReferenceObject>(json);
  913. TestComponentSimple c2 = o2.Data.Prop1;
  914. TestComponentSimple c3 = o2.Data.Prop2;
  915. TestComponentSimple c4 = o2.Data.Data[0];
  916. Assert.IsTrue(ReferenceEquals(c2, c3));
  917. Assert.IsFalse(ReferenceEquals(c2, c4));
  918. }
  919. }
  920. public class PropertyItemIsReferenceBody
  921. {
  922. public TestComponentSimple Prop1 { get; set; }
  923. public TestComponentSimple Prop2 { get; set; }
  924. public IList<TestComponentSimple> Data { get; set; }
  925. }
  926. public class PropertyItemIsReferenceObject
  927. {
  928. [JsonProperty(ItemIsReference = true)]
  929. public PropertyItemIsReferenceBody Data { get; set; }
  930. }
  931. public class PropertyItemIsReferenceList
  932. {
  933. [JsonProperty(ItemIsReference = true)]
  934. public IList<IList<object>> Data { get; set; }
  935. }
  936. [JsonArray(ItemIsReference = true)]
  937. public class ReferencedList<T> : List<T>
  938. {
  939. }
  940. [JsonDictionary(ItemIsReference = true)]
  941. public class ReferencedDictionary<T> : Dictionary<string, T>
  942. {
  943. }
  944. [JsonObject(ItemIsReference = true)]
  945. public class ReferenceObject
  946. {
  947. public TestComponentSimple Component1 { get; set; }
  948. public TestComponentSimple Component2 { get; set; }
  949. [JsonProperty(IsReference = false)]
  950. public TestComponentSimple ComponentNotReference { get; set; }
  951. public string String { get; set; }
  952. public int Integer { get; set; }
  953. }
  954. }