PageRenderTime 71ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/Ecarestia/newtonsoft.json
C# | 2538 lines | 2208 code | 234 blank | 96 comment | 44 complexity | 3549c8bf3b2937013152eeb8adb41132 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;
  27. using System.Collections.Specialized;
  28. using System.Runtime.Serialization;
  29. #if !(NET35 || NET20 || PORTABLE || PORTABLE40)
  30. using System.Collections.Concurrent;
  31. #endif
  32. using System.Collections.Generic;
  33. using System.Collections.ObjectModel;
  34. using System.Globalization;
  35. using System.IO;
  36. #if NET20
  37. using Newtonsoft.Json.Utilities.LinqBridge;
  38. #else
  39. using System.Linq;
  40. #endif
  41. using System.Text;
  42. using System.Xml;
  43. using Newtonsoft.Json.Linq;
  44. using Newtonsoft.Json.Serialization;
  45. using Newtonsoft.Json.Tests.TestObjects;
  46. using Newtonsoft.Json.Tests.TestObjects.Events;
  47. using Newtonsoft.Json.Tests.TestObjects.Organization;
  48. using Newtonsoft.Json.Utilities;
  49. #if DNXCORE50
  50. using Xunit;
  51. using Test = Xunit.FactAttribute;
  52. using Assert = Newtonsoft.Json.Tests.XUnitAssert;
  53. #else
  54. using NUnit.Framework;
  55. #endif
  56. #if !NET20 && !PORTABLE40
  57. using System.Xml.Linq;
  58. #endif
  59. namespace Newtonsoft.Json.Tests.Serialization
  60. {
  61. [TestFixture]
  62. public class JsonSerializerCollectionsTests : TestFixtureBase
  63. {
  64. [Test]
  65. public void DoubleKey_WholeValue()
  66. {
  67. Dictionary<double, int> dictionary = new Dictionary<double, int> { { 1d, 1 } };
  68. string output = JsonConvert.SerializeObject(dictionary);
  69. Assert.AreEqual(@"{""1"":1}", output);
  70. Dictionary<double, int> deserializedValue = JsonConvert.DeserializeObject<Dictionary<double, int>>(output);
  71. Assert.AreEqual(1d, deserializedValue.First().Key);
  72. }
  73. [Test]
  74. public void DoubleKey_MaxValue()
  75. {
  76. Dictionary<double, int> dictionary = new Dictionary<double, int> { { double.MaxValue, 1 } };
  77. string output = JsonConvert.SerializeObject(dictionary);
  78. Assert.AreEqual(@"{""1.7976931348623157E+308"":1}", output);
  79. Dictionary<double, int> deserializedValue = JsonConvert.DeserializeObject<Dictionary<double, int>>(output);
  80. Assert.AreEqual(double.MaxValue, deserializedValue.First().Key);
  81. }
  82. [Test]
  83. public void FloatKey_MaxValue()
  84. {
  85. Dictionary<float, int> dictionary = new Dictionary<float, int> { { float.MaxValue, 1 } };
  86. string output = JsonConvert.SerializeObject(dictionary);
  87. Assert.AreEqual(@"{""3.40282347E+38"":1}", output);
  88. Dictionary<float, int> deserializedValue = JsonConvert.DeserializeObject<Dictionary<float, int>>(output);
  89. Assert.AreEqual(float.MaxValue, deserializedValue.First().Key);
  90. }
  91. public class TestCollectionPrivateParameterized : IEnumerable<int>
  92. {
  93. private readonly List<int> _bars;
  94. public TestCollectionPrivateParameterized()
  95. {
  96. _bars = new List<int>();
  97. }
  98. [JsonConstructor]
  99. private TestCollectionPrivateParameterized(IEnumerable<int> bars)
  100. {
  101. _bars = new List<int>(bars);
  102. }
  103. public void Add(int bar)
  104. {
  105. _bars.Add(bar);
  106. }
  107. public IEnumerator<int> GetEnumerator() => _bars.GetEnumerator();
  108. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  109. }
  110. [Test]
  111. public void CollectionJsonConstructorPrivateParameterized()
  112. {
  113. TestCollectionPrivateParameterized c1 = new TestCollectionPrivateParameterized();
  114. c1.Add(0);
  115. c1.Add(1);
  116. c1.Add(2);
  117. string json = JsonConvert.SerializeObject(c1);
  118. TestCollectionPrivateParameterized c2 = JsonConvert.DeserializeObject<TestCollectionPrivateParameterized>(json);
  119. List<int> values = c2.ToList();
  120. Assert.AreEqual(3, values.Count);
  121. Assert.AreEqual(0, values[0]);
  122. Assert.AreEqual(1, values[1]);
  123. Assert.AreEqual(2, values[2]);
  124. }
  125. public class TestCollectionPrivate : List<int>
  126. {
  127. [JsonConstructor]
  128. private TestCollectionPrivate()
  129. {
  130. }
  131. public static TestCollectionPrivate Create()
  132. {
  133. return new TestCollectionPrivate();
  134. }
  135. }
  136. [Test]
  137. public void CollectionJsonConstructorPrivate()
  138. {
  139. TestCollectionPrivate c1 = TestCollectionPrivate.Create();
  140. c1.Add(0);
  141. c1.Add(1);
  142. c1.Add(2);
  143. string json = JsonConvert.SerializeObject(c1);
  144. TestCollectionPrivate c2 = JsonConvert.DeserializeObject<TestCollectionPrivate>(json);
  145. List<int> values = c2.ToList();
  146. Assert.AreEqual(3, values.Count);
  147. Assert.AreEqual(0, values[0]);
  148. Assert.AreEqual(1, values[1]);
  149. Assert.AreEqual(2, values[2]);
  150. }
  151. public class TestCollectionMultipleParameters : List<int>
  152. {
  153. [JsonConstructor]
  154. public TestCollectionMultipleParameters(string s1, string s2)
  155. {
  156. }
  157. }
  158. [Test]
  159. public void CollectionJsonConstructorMultipleParameters()
  160. {
  161. ExceptionAssert.Throws<JsonException>(
  162. () => JsonConvert.SerializeObject(new TestCollectionMultipleParameters(null, null)),
  163. "Constructor for 'Newtonsoft.Json.Tests.Serialization.JsonSerializerCollectionsTests+TestCollectionMultipleParameters' must have no parameters or a single parameter that implements 'System.Collections.Generic.IEnumerable`1[System.Int32]'.");
  164. }
  165. public class TestCollectionBadIEnumerableParameter : List<int>
  166. {
  167. [JsonConstructor]
  168. public TestCollectionBadIEnumerableParameter(List<string> l)
  169. {
  170. }
  171. }
  172. [Test]
  173. public void CollectionJsonConstructorBadIEnumerableParameter()
  174. {
  175. ExceptionAssert.Throws<JsonException>(
  176. () => JsonConvert.SerializeObject(new TestCollectionBadIEnumerableParameter(null)),
  177. "Constructor for 'Newtonsoft.Json.Tests.Serialization.JsonSerializerCollectionsTests+TestCollectionBadIEnumerableParameter' must have no parameters or a single parameter that implements 'System.Collections.Generic.IEnumerable`1[System.Int32]'.");
  178. }
  179. #if !(DNXCORE50 || PORTABLE)
  180. public class TestCollectionNonGeneric : ArrayList
  181. {
  182. [JsonConstructor]
  183. public TestCollectionNonGeneric(IEnumerable l)
  184. : base(l.Cast<object>().ToList())
  185. {
  186. }
  187. }
  188. [Test]
  189. public void CollectionJsonConstructorNonGeneric()
  190. {
  191. string json = @"[1,2,3]";
  192. TestCollectionNonGeneric l = JsonConvert.DeserializeObject<TestCollectionNonGeneric>(json);
  193. Assert.AreEqual(3, l.Count);
  194. Assert.AreEqual(1, l[0]);
  195. Assert.AreEqual(2, l[1]);
  196. Assert.AreEqual(3, l[2]);
  197. }
  198. #endif
  199. public class TestDictionaryPrivateParameterized : Dictionary<string, int>
  200. {
  201. public TestDictionaryPrivateParameterized()
  202. {
  203. }
  204. [JsonConstructor]
  205. private TestDictionaryPrivateParameterized(IEnumerable<KeyValuePair<string, int>> bars)
  206. : base(bars.ToDictionary(k => k.Key, k => k.Value))
  207. {
  208. }
  209. }
  210. [Test]
  211. public void DictionaryJsonConstructorPrivateParameterized()
  212. {
  213. TestDictionaryPrivateParameterized c1 = new TestDictionaryPrivateParameterized();
  214. c1.Add("zero", 0);
  215. c1.Add("one", 1);
  216. c1.Add("two", 2);
  217. string json = JsonConvert.SerializeObject(c1);
  218. TestDictionaryPrivateParameterized c2 = JsonConvert.DeserializeObject<TestDictionaryPrivateParameterized>(json);
  219. Assert.AreEqual(3, c2.Count);
  220. Assert.AreEqual(0, c2["zero"]);
  221. Assert.AreEqual(1, c2["one"]);
  222. Assert.AreEqual(2, c2["two"]);
  223. }
  224. public class TestDictionaryPrivate : Dictionary<string, int>
  225. {
  226. [JsonConstructor]
  227. private TestDictionaryPrivate()
  228. {
  229. }
  230. public static TestDictionaryPrivate Create()
  231. {
  232. return new TestDictionaryPrivate();
  233. }
  234. }
  235. [Test]
  236. public void DictionaryJsonConstructorPrivate()
  237. {
  238. TestDictionaryPrivate c1 = TestDictionaryPrivate.Create();
  239. c1.Add("zero", 0);
  240. c1.Add("one", 1);
  241. c1.Add("two", 2);
  242. string json = JsonConvert.SerializeObject(c1);
  243. TestDictionaryPrivate c2 = JsonConvert.DeserializeObject<TestDictionaryPrivate>(json);
  244. Assert.AreEqual(3, c2.Count);
  245. Assert.AreEqual(0, c2["zero"]);
  246. Assert.AreEqual(1, c2["one"]);
  247. Assert.AreEqual(2, c2["two"]);
  248. }
  249. public class TestDictionaryMultipleParameters : Dictionary<string, int>
  250. {
  251. [JsonConstructor]
  252. public TestDictionaryMultipleParameters(string s1, string s2)
  253. {
  254. }
  255. }
  256. [Test]
  257. public void DictionaryJsonConstructorMultipleParameters()
  258. {
  259. ExceptionAssert.Throws<JsonException>(
  260. () => JsonConvert.SerializeObject(new TestDictionaryMultipleParameters(null, null)),
  261. "Constructor for 'Newtonsoft.Json.Tests.Serialization.JsonSerializerCollectionsTests+TestDictionaryMultipleParameters' must have no parameters or a single parameter that implements 'System.Collections.Generic.IEnumerable`1[System.Collections.Generic.KeyValuePair`2[System.String,System.Int32]]'.");
  262. }
  263. public class TestDictionaryBadIEnumerableParameter : Dictionary<string, int>
  264. {
  265. [JsonConstructor]
  266. public TestDictionaryBadIEnumerableParameter(Dictionary<string, string> l)
  267. {
  268. }
  269. }
  270. [Test]
  271. public void DictionaryJsonConstructorBadIEnumerableParameter()
  272. {
  273. ExceptionAssert.Throws<JsonException>(
  274. () => JsonConvert.SerializeObject(new TestDictionaryBadIEnumerableParameter(null)),
  275. "Constructor for 'Newtonsoft.Json.Tests.Serialization.JsonSerializerCollectionsTests+TestDictionaryBadIEnumerableParameter' must have no parameters or a single parameter that implements 'System.Collections.Generic.IEnumerable`1[System.Collections.Generic.KeyValuePair`2[System.String,System.Int32]]'.");
  276. }
  277. #if !(DNXCORE50 || PORTABLE)
  278. public class TestDictionaryNonGeneric : Hashtable
  279. {
  280. [JsonConstructor]
  281. public TestDictionaryNonGeneric(IDictionary d)
  282. : base(d)
  283. {
  284. }
  285. }
  286. [Test]
  287. public void DictionaryJsonConstructorNonGeneric()
  288. {
  289. string json = @"{'zero':0,'one':1,'two':2}";
  290. TestDictionaryNonGeneric d = JsonConvert.DeserializeObject<TestDictionaryNonGeneric>(json);
  291. Assert.AreEqual(3, d.Count);
  292. Assert.AreEqual(0, d["zero"]);
  293. Assert.AreEqual(1, d["one"]);
  294. Assert.AreEqual(2, d["two"]);
  295. }
  296. #endif
  297. #if !(DNXCORE50)
  298. public class NameValueCollectionTestClass
  299. {
  300. public NameValueCollection Collection { get; set; }
  301. }
  302. [Test]
  303. public void DeserializeNameValueCollection()
  304. {
  305. ExceptionAssert.Throws<JsonSerializationException>(
  306. () => JsonConvert.DeserializeObject<NameValueCollectionTestClass>("{Collection:[]}"),
  307. "Cannot create and populate list type System.Collections.Specialized.NameValueCollection. Path 'Collection', line 1, position 13.");
  308. }
  309. #endif
  310. #if !(NET35 || NET20 || PORTABLE || PORTABLE40)
  311. public class SomeObject
  312. {
  313. public string Text1 { get; set; }
  314. }
  315. public class CustomConcurrentDictionary : ConcurrentDictionary<string, List<SomeObject>>
  316. {
  317. [OnDeserialized]
  318. internal void OnDeserializedMethod(StreamingContext context)
  319. {
  320. ((IDictionary)this).Add("key2", new List<SomeObject>
  321. {
  322. new SomeObject
  323. {
  324. Text1 = "value2"
  325. }
  326. });
  327. }
  328. }
  329. [Test]
  330. public void SerializeCustomConcurrentDictionary()
  331. {
  332. IDictionary d = new CustomConcurrentDictionary();
  333. d.Add("key", new List<SomeObject>
  334. {
  335. new SomeObject
  336. {
  337. Text1 = "value1"
  338. }
  339. });
  340. string json = JsonConvert.SerializeObject(d, Formatting.Indented);
  341. Assert.AreEqual(@"{
  342. ""key"": [
  343. {
  344. ""Text1"": ""value1""
  345. }
  346. ]
  347. }", json);
  348. CustomConcurrentDictionary d2 = JsonConvert.DeserializeObject<CustomConcurrentDictionary>(json);
  349. Assert.AreEqual(2, d2.Count);
  350. Assert.AreEqual("value1", d2["key"][0].Text1);
  351. Assert.AreEqual("value2", d2["key2"][0].Text1);
  352. }
  353. #endif
  354. [Test]
  355. public void NonZeroBasedArray()
  356. {
  357. var onebasedArray = Array.CreateInstance(typeof(string), new[] { 3 }, new[] { 2 });
  358. for (var i = onebasedArray.GetLowerBound(0); i <= onebasedArray.GetUpperBound(0); i++)
  359. {
  360. onebasedArray.SetValue(i.ToString(CultureInfo.InvariantCulture), new[] { i, });
  361. }
  362. string output = JsonConvert.SerializeObject(onebasedArray, Formatting.Indented);
  363. StringAssert.AreEqual(@"[
  364. ""2"",
  365. ""3"",
  366. ""4""
  367. ]", output);
  368. }
  369. [Test]
  370. public void NonZeroBasedMultiArray()
  371. {
  372. // lets create a two dimensional array, each rank is 1-based of with a capacity of 4.
  373. var onebasedArray = Array.CreateInstance(typeof(string), new[] { 3, 3 }, new[] { 1, 2 });
  374. // Iterate of the array elements and assign a random double
  375. for (var i = onebasedArray.GetLowerBound(0); i <= onebasedArray.GetUpperBound(0); i++)
  376. {
  377. for (var j = onebasedArray.GetLowerBound(1); j <= onebasedArray.GetUpperBound(1); j++)
  378. {
  379. onebasedArray.SetValue(i + "_" + j, new[] { i, j });
  380. }
  381. }
  382. // Now lets try and serialize the Array
  383. string output = JsonConvert.SerializeObject(onebasedArray, Formatting.Indented);
  384. StringAssert.AreEqual(@"[
  385. [
  386. ""1_2"",
  387. ""1_3"",
  388. ""1_4""
  389. ],
  390. [
  391. ""2_2"",
  392. ""2_3"",
  393. ""2_4""
  394. ],
  395. [
  396. ""3_2"",
  397. ""3_3"",
  398. ""3_4""
  399. ]
  400. ]", output);
  401. }
  402. [Test]
  403. public void MultiDObjectArray()
  404. {
  405. object[,] myOtherArray =
  406. {
  407. { new KeyValuePair<string, double>("my value", 0.8), "foobar" },
  408. { true, 0.4d },
  409. { 0.05f, 6 }
  410. };
  411. string myOtherArrayAsString = JsonConvert.SerializeObject(myOtherArray, Formatting.Indented);
  412. StringAssert.AreEqual(@"[
  413. [
  414. {
  415. ""Key"": ""my value"",
  416. ""Value"": 0.8
  417. },
  418. ""foobar""
  419. ],
  420. [
  421. true,
  422. 0.4
  423. ],
  424. [
  425. 0.05,
  426. 6
  427. ]
  428. ]", myOtherArrayAsString);
  429. JObject o = JObject.Parse(@"{
  430. ""Key"": ""my value"",
  431. ""Value"": 0.8
  432. }");
  433. object[,] myOtherResult = JsonConvert.DeserializeObject<object[,]>(myOtherArrayAsString);
  434. Assert.IsTrue(JToken.DeepEquals(o, (JToken)myOtherResult[0, 0]));
  435. Assert.AreEqual("foobar", myOtherResult[0, 1]);
  436. Assert.AreEqual(true, myOtherResult[1, 0]);
  437. Assert.AreEqual(0.4, myOtherResult[1, 1]);
  438. Assert.AreEqual(0.05, myOtherResult[2, 0]);
  439. Assert.AreEqual(6L, myOtherResult[2, 1]);
  440. }
  441. public class EnumerableClass<T> : IEnumerable<T>
  442. {
  443. private readonly IList<T> _values;
  444. public EnumerableClass(IEnumerable<T> values)
  445. {
  446. _values = new List<T>(values);
  447. }
  448. public IEnumerator<T> GetEnumerator()
  449. {
  450. return _values.GetEnumerator();
  451. }
  452. IEnumerator IEnumerable.GetEnumerator()
  453. {
  454. return GetEnumerator();
  455. }
  456. }
  457. [Test]
  458. public void DeserializeIEnumerableFromConstructor()
  459. {
  460. string json = @"[
  461. 1,
  462. 2,
  463. null
  464. ]";
  465. var result = JsonConvert.DeserializeObject<EnumerableClass<int?>>(json);
  466. Assert.AreEqual(3, result.Count());
  467. Assert.AreEqual(1, result.ElementAt(0));
  468. Assert.AreEqual(2, result.ElementAt(1));
  469. Assert.AreEqual(null, result.ElementAt(2));
  470. }
  471. public class EnumerableClassFailure<T> : IEnumerable<T>
  472. {
  473. private readonly IList<T> _values;
  474. public EnumerableClassFailure()
  475. {
  476. _values = new List<T>();
  477. }
  478. public IEnumerator<T> GetEnumerator()
  479. {
  480. return _values.GetEnumerator();
  481. }
  482. IEnumerator IEnumerable.GetEnumerator()
  483. {
  484. return GetEnumerator();
  485. }
  486. }
  487. [Test]
  488. public void DeserializeIEnumerableFromConstructor_Failure()
  489. {
  490. string json = @"[
  491. ""One"",
  492. ""II"",
  493. ""3""
  494. ]";
  495. ExceptionAssert.Throws<JsonSerializationException>(() => JsonConvert.DeserializeObject<EnumerableClassFailure<string>>(json), "Cannot create and populate list type Newtonsoft.Json.Tests.Serialization.JsonSerializerCollectionsTests+EnumerableClassFailure`1[System.String]. Path '', line 1, position 1.");
  496. }
  497. public class PrivateDefaultCtorList<T> : List<T>
  498. {
  499. private PrivateDefaultCtorList()
  500. {
  501. }
  502. }
  503. [Test]
  504. public void DeserializePrivateListCtor()
  505. {
  506. ExceptionAssert.Throws<JsonSerializationException>(() => JsonConvert.DeserializeObject<PrivateDefaultCtorList<int>>("[1,2]"), "Unable to find a constructor to use for type Newtonsoft.Json.Tests.Serialization.JsonSerializerCollectionsTests+PrivateDefaultCtorList`1[System.Int32]. Path '', line 1, position 1.");
  507. var list = JsonConvert.DeserializeObject<PrivateDefaultCtorList<int>>("[1,2]", new JsonSerializerSettings
  508. {
  509. ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
  510. });
  511. Assert.AreEqual(2, list.Count);
  512. }
  513. public class PrivateDefaultCtorWithIEnumerableCtorList<T> : List<T>
  514. {
  515. private PrivateDefaultCtorWithIEnumerableCtorList()
  516. {
  517. }
  518. public PrivateDefaultCtorWithIEnumerableCtorList(IEnumerable<T> values)
  519. : base(values)
  520. {
  521. Add(default(T));
  522. }
  523. }
  524. [Test]
  525. public void DeserializePrivateListConstructor()
  526. {
  527. var list = JsonConvert.DeserializeObject<PrivateDefaultCtorWithIEnumerableCtorList<int>>("[1,2]");
  528. Assert.AreEqual(3, list.Count);
  529. Assert.AreEqual(1, list[0]);
  530. Assert.AreEqual(2, list[1]);
  531. Assert.AreEqual(0, list[2]);
  532. }
  533. [Test]
  534. public void DeserializeNonIsoDateDictionaryKey()
  535. {
  536. Dictionary<DateTime, string> d = JsonConvert.DeserializeObject<Dictionary<DateTime, string>>(@"{""04/28/2013 00:00:00"":""test""}");
  537. Assert.AreEqual(1, d.Count);
  538. DateTime key = DateTime.Parse("04/28/2013 00:00:00", CultureInfo.InvariantCulture);
  539. Assert.AreEqual("test", d[key]);
  540. }
  541. [Test]
  542. public void DeserializeNonGenericList()
  543. {
  544. IList l = JsonConvert.DeserializeObject<IList>("['string!']");
  545. Assert.AreEqual(typeof(List<object>), l.GetType());
  546. Assert.AreEqual(1, l.Count);
  547. Assert.AreEqual("string!", l[0]);
  548. }
  549. #if !(NET40 || NET35 || NET20 || PORTABLE40)
  550. [Test]
  551. public void DeserializeReadOnlyListInterface()
  552. {
  553. IReadOnlyList<int> list = JsonConvert.DeserializeObject<IReadOnlyList<int>>("[1,2,3]");
  554. Assert.AreEqual(3, list.Count);
  555. Assert.AreEqual(1, list[0]);
  556. Assert.AreEqual(2, list[1]);
  557. Assert.AreEqual(3, list[2]);
  558. }
  559. [Test]
  560. public void DeserializeReadOnlyCollectionInterface()
  561. {
  562. IReadOnlyCollection<int> list = JsonConvert.DeserializeObject<IReadOnlyCollection<int>>("[1,2,3]");
  563. Assert.AreEqual(3, list.Count);
  564. Assert.AreEqual(1, list.ElementAt(0));
  565. Assert.AreEqual(2, list.ElementAt(1));
  566. Assert.AreEqual(3, list.ElementAt(2));
  567. }
  568. [Test]
  569. public void DeserializeReadOnlyCollection()
  570. {
  571. ReadOnlyCollection<int> list = JsonConvert.DeserializeObject<ReadOnlyCollection<int>>("[1,2,3]");
  572. Assert.AreEqual(3, list.Count);
  573. Assert.AreEqual(1, list[0]);
  574. Assert.AreEqual(2, list[1]);
  575. Assert.AreEqual(3, list[2]);
  576. }
  577. [Test]
  578. public void DeserializeReadOnlyDictionaryInterface()
  579. {
  580. IReadOnlyDictionary<string, int> dic = JsonConvert.DeserializeObject<IReadOnlyDictionary<string, int>>("{'one':1,'two':2}");
  581. Assert.AreEqual(2, dic.Count);
  582. Assert.AreEqual(1, dic["one"]);
  583. Assert.AreEqual(2, dic["two"]);
  584. CustomAssert.IsInstanceOfType(typeof(ReadOnlyDictionary<string, int>), dic);
  585. }
  586. [Test]
  587. public void DeserializeReadOnlyDictionary()
  588. {
  589. ReadOnlyDictionary<string, int> dic = JsonConvert.DeserializeObject<ReadOnlyDictionary<string, int>>("{'one':1,'two':2}");
  590. Assert.AreEqual(2, dic.Count);
  591. Assert.AreEqual(1, dic["one"]);
  592. Assert.AreEqual(2, dic["two"]);
  593. }
  594. public class CustomReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
  595. {
  596. private readonly IDictionary<TKey, TValue> _dictionary;
  597. public CustomReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
  598. {
  599. _dictionary = dictionary;
  600. }
  601. public bool ContainsKey(TKey key)
  602. {
  603. return _dictionary.ContainsKey(key);
  604. }
  605. public IEnumerable<TKey> Keys
  606. {
  607. get { return _dictionary.Keys; }
  608. }
  609. public bool TryGetValue(TKey key, out TValue value)
  610. {
  611. return _dictionary.TryGetValue(key, out value);
  612. }
  613. public IEnumerable<TValue> Values
  614. {
  615. get { return _dictionary.Values; }
  616. }
  617. public TValue this[TKey key]
  618. {
  619. get { return _dictionary[key]; }
  620. }
  621. public int Count
  622. {
  623. get { return _dictionary.Count; }
  624. }
  625. public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
  626. {
  627. return _dictionary.GetEnumerator();
  628. }
  629. IEnumerator IEnumerable.GetEnumerator()
  630. {
  631. return _dictionary.GetEnumerator();
  632. }
  633. }
  634. [Test]
  635. public void SerializeCustomReadOnlyDictionary()
  636. {
  637. IDictionary<string, int> d = new Dictionary<string, int>
  638. {
  639. { "one", 1 },
  640. { "two", 2 }
  641. };
  642. CustomReadOnlyDictionary<string, int> dic = new CustomReadOnlyDictionary<string, int>(d);
  643. string json = JsonConvert.SerializeObject(dic, Formatting.Indented);
  644. StringAssert.AreEqual(@"{
  645. ""one"": 1,
  646. ""two"": 2
  647. }", json);
  648. }
  649. public class CustomReadOnlyCollection<T> : IReadOnlyCollection<T>
  650. {
  651. private readonly IList<T> _values;
  652. public CustomReadOnlyCollection(IList<T> values)
  653. {
  654. _values = values;
  655. }
  656. public int Count
  657. {
  658. get { return _values.Count; }
  659. }
  660. public IEnumerator<T> GetEnumerator()
  661. {
  662. return _values.GetEnumerator();
  663. }
  664. IEnumerator IEnumerable.GetEnumerator()
  665. {
  666. return _values.GetEnumerator();
  667. }
  668. }
  669. [Test]
  670. public void SerializeCustomReadOnlyCollection()
  671. {
  672. IList<int> l = new List<int>
  673. {
  674. 1,
  675. 2,
  676. 3
  677. };
  678. CustomReadOnlyCollection<int> list = new CustomReadOnlyCollection<int>(l);
  679. string json = JsonConvert.SerializeObject(list, Formatting.Indented);
  680. StringAssert.AreEqual(@"[
  681. 1,
  682. 2,
  683. 3
  684. ]", json);
  685. }
  686. #endif
  687. [Test]
  688. public void TestEscapeDictionaryStrings()
  689. {
  690. const string s = @"host\user";
  691. string serialized = JsonConvert.SerializeObject(s);
  692. Assert.AreEqual(@"""host\\user""", serialized);
  693. Dictionary<int, object> d1 = new Dictionary<int, object>();
  694. d1.Add(5, s);
  695. Assert.AreEqual(@"{""5"":""host\\user""}", JsonConvert.SerializeObject(d1));
  696. Dictionary<string, object> d2 = new Dictionary<string, object>();
  697. d2.Add(s, 5);
  698. Assert.AreEqual(@"{""host\\user"":5}", JsonConvert.SerializeObject(d2));
  699. }
  700. public class GenericListTestClass
  701. {
  702. public List<string> GenericList { get; set; }
  703. public GenericListTestClass()
  704. {
  705. GenericList = new List<string>();
  706. }
  707. }
  708. [Test]
  709. public void DeserializeExistingGenericList()
  710. {
  711. GenericListTestClass c = new GenericListTestClass();
  712. c.GenericList.Add("1");
  713. c.GenericList.Add("2");
  714. string json = JsonConvert.SerializeObject(c, Formatting.Indented);
  715. GenericListTestClass newValue = JsonConvert.DeserializeObject<GenericListTestClass>(json);
  716. Assert.AreEqual(2, newValue.GenericList.Count);
  717. Assert.AreEqual(typeof(List<string>), newValue.GenericList.GetType());
  718. }
  719. [Test]
  720. public void DeserializeSimpleKeyValuePair()
  721. {
  722. List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
  723. list.Add(new KeyValuePair<string, string>("key1", "value1"));
  724. list.Add(new KeyValuePair<string, string>("key2", "value2"));
  725. string json = JsonConvert.SerializeObject(list);
  726. Assert.AreEqual(@"[{""Key"":""key1"",""Value"":""value1""},{""Key"":""key2"",""Value"":""value2""}]", json);
  727. List<KeyValuePair<string, string>> result = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(json);
  728. Assert.AreEqual(2, result.Count);
  729. Assert.AreEqual("key1", result[0].Key);
  730. Assert.AreEqual("value1", result[0].Value);
  731. Assert.AreEqual("key2", result[1].Key);
  732. Assert.AreEqual("value2", result[1].Value);
  733. }
  734. [Test]
  735. public void DeserializeComplexKeyValuePair()
  736. {
  737. DateTime dateTime = new DateTime(2000, 12, 1, 23, 1, 1, DateTimeKind.Utc);
  738. List<KeyValuePair<string, WagePerson>> list = new List<KeyValuePair<string, WagePerson>>();
  739. list.Add(new KeyValuePair<string, WagePerson>("key1", new WagePerson
  740. {
  741. BirthDate = dateTime,
  742. Department = "Department1",
  743. LastModified = dateTime,
  744. HourlyWage = 1
  745. }));
  746. list.Add(new KeyValuePair<string, WagePerson>("key2", new WagePerson
  747. {
  748. BirthDate = dateTime,
  749. Department = "Department2",
  750. LastModified = dateTime,
  751. HourlyWage = 2
  752. }));
  753. string json = JsonConvert.SerializeObject(list, Formatting.Indented);
  754. StringAssert.AreEqual(@"[
  755. {
  756. ""Key"": ""key1"",
  757. ""Value"": {
  758. ""HourlyWage"": 1.0,
  759. ""Name"": null,
  760. ""BirthDate"": ""2000-12-01T23:01:01Z"",
  761. ""LastModified"": ""2000-12-01T23:01:01Z""
  762. }
  763. },
  764. {
  765. ""Key"": ""key2"",
  766. ""Value"": {
  767. ""HourlyWage"": 2.0,
  768. ""Name"": null,
  769. ""BirthDate"": ""2000-12-01T23:01:01Z"",
  770. ""LastModified"": ""2000-12-01T23:01:01Z""
  771. }
  772. }
  773. ]", json);
  774. List<KeyValuePair<string, WagePerson>> result = JsonConvert.DeserializeObject<List<KeyValuePair<string, WagePerson>>>(json);
  775. Assert.AreEqual(2, result.Count);
  776. Assert.AreEqual("key1", result[0].Key);
  777. Assert.AreEqual(1, result[0].Value.HourlyWage);
  778. Assert.AreEqual("key2", result[1].Key);
  779. Assert.AreEqual(2, result[1].Value.HourlyWage);
  780. }
  781. [Test]
  782. public void StringListAppenderConverterTest()
  783. {
  784. Movie p = new Movie();
  785. p.ReleaseCountries = new List<string> { "Existing" };
  786. JsonConvert.PopulateObject("{'ReleaseCountries':['Appended']}", p, new JsonSerializerSettings
  787. {
  788. Converters = new List<JsonConverter> { new StringListAppenderConverter() }
  789. });
  790. Assert.AreEqual(2, p.ReleaseCountries.Count);
  791. Assert.AreEqual("Existing", p.ReleaseCountries[0]);
  792. Assert.AreEqual("Appended", p.ReleaseCountries[1]);
  793. }
  794. [Test]
  795. public void StringAppenderConverterTest()
  796. {
  797. Movie p = new Movie();
  798. p.Name = "Existing,";
  799. JsonConvert.PopulateObject("{'Name':'Appended'}", p, new JsonSerializerSettings
  800. {
  801. Converters = new List<JsonConverter> { new StringAppenderConverter() }
  802. });
  803. Assert.AreEqual("Existing,Appended", p.Name);
  804. }
  805. [Test]
  806. public void DeserializeIDictionary()
  807. {
  808. IDictionary dictionary = JsonConvert.DeserializeObject<IDictionary>("{'name':'value!'}");
  809. Assert.AreEqual(1, dictionary.Count);
  810. Assert.AreEqual("value!", dictionary["name"]);
  811. }
  812. [Test]
  813. public void DeserializeIList()
  814. {
  815. IList list = JsonConvert.DeserializeObject<IList>("['1', 'two', 'III']");
  816. Assert.AreEqual(3, list.Count);
  817. }
  818. [Test]
  819. public void NullableValueGenericDictionary()
  820. {
  821. IDictionary<string, int?> v1 = new Dictionary<string, int?>
  822. {
  823. { "First", 1 },
  824. { "Second", null },
  825. { "Third", 3 }
  826. };
  827. string json = JsonConvert.SerializeObject(v1, Formatting.Indented);
  828. StringAssert.AreEqual(@"{
  829. ""First"": 1,
  830. ""Second"": null,
  831. ""Third"": 3
  832. }", json);
  833. IDictionary<string, int?> v2 = JsonConvert.DeserializeObject<IDictionary<string, int?>>(json);
  834. Assert.AreEqual(3, v2.Count);
  835. Assert.AreEqual(1, v2["First"]);
  836. Assert.AreEqual(null, v2["Second"]);
  837. Assert.AreEqual(3, v2["Third"]);
  838. }
  839. #if !(NET35 || NET20 || PORTABLE || PORTABLE40)
  840. [Test]
  841. public void DeserializeConcurrentDictionary()
  842. {
  843. IDictionary<string, TestObjects.Component> components = new Dictionary<string, TestObjects.Component>
  844. {
  845. { "Key!", new TestObjects.Component() }
  846. };
  847. GameObject go = new GameObject
  848. {
  849. Components = new ConcurrentDictionary<string, TestObjects.Component>(components),
  850. Id = "Id!",
  851. Name = "Name!"
  852. };
  853. string originalJson = JsonConvert.SerializeObject(go, Formatting.Indented);
  854. StringAssert.AreEqual(@"{
  855. ""Components"": {
  856. ""Key!"": {}
  857. },
  858. ""Id"": ""Id!"",
  859. ""Name"": ""Name!""
  860. }", originalJson);
  861. GameObject newObject = JsonConvert.DeserializeObject<GameObject>(originalJson);
  862. Assert.AreEqual(1, newObject.Components.Count);
  863. Assert.AreEqual("Id!", newObject.Id);
  864. Assert.AreEqual("Name!", newObject.Name);
  865. }
  866. #endif
  867. [Test]
  868. public void DeserializeKeyValuePairArray()
  869. {
  870. string json = @"[ { ""Value"": [ ""1"", ""2"" ], ""Key"": ""aaa"", ""BadContent"": [ 0 ] }, { ""Value"": [ ""3"", ""4"" ], ""Key"": ""bbb"" } ]";
  871. IList<KeyValuePair<string, IList<string>>> values = JsonConvert.DeserializeObject<IList<KeyValuePair<string, IList<string>>>>(json);
  872. Assert.AreEqual(2, values.Count);
  873. Assert.AreEqual("aaa", values[0].Key);
  874. Assert.AreEqual(2, values[0].Value.Count);
  875. Assert.AreEqual("1", values[0].Value[0]);
  876. Assert.AreEqual("2", values[0].Value[1]);
  877. Assert.AreEqual("bbb", values[1].Key);
  878. Assert.AreEqual(2, values[1].Value.Count);
  879. Assert.AreEqual("3", values[1].Value[0]);
  880. Assert.AreEqual("4", values[1].Value[1]);
  881. }
  882. [Test]
  883. public void DeserializeNullableKeyValuePairArray()
  884. {
  885. string json = @"[ { ""Value"": [ ""1"", ""2"" ], ""Key"": ""aaa"", ""BadContent"": [ 0 ] }, null, { ""Value"": [ ""3"", ""4"" ], ""Key"": ""bbb"" } ]";
  886. IList<KeyValuePair<string, IList<string>>?> values = JsonConvert.DeserializeObject<IList<KeyValuePair<string, IList<string>>?>>(json);
  887. Assert.AreEqual(3, values.Count);
  888. Assert.AreEqual("aaa", values[0].Value.Key);
  889. Assert.AreEqual(2, values[0].Value.Value.Count);
  890. Assert.AreEqual("1", values[0].Value.Value[0]);
  891. Assert.AreEqual("2", values[0].Value.Value[1]);
  892. Assert.AreEqual(null, values[1]);
  893. Assert.AreEqual("bbb", values[2].Value.Key);
  894. Assert.AreEqual(2, values[2].Value.Value.Count);
  895. Assert.AreEqual("3", values[2].Value.Value[0]);
  896. Assert.AreEqual("4", values[2].Value.Value[1]);
  897. }
  898. [Test]
  899. public void DeserializeNullToNonNullableKeyValuePairArray()
  900. {
  901. string json = @"[ null ]";
  902. ExceptionAssert.Throws<JsonSerializationException>(() => { JsonConvert.DeserializeObject<IList<KeyValuePair<string, IList<string>>>>(json); }, "Cannot convert null value to KeyValuePair. Path '[0]', line 1, position 6.");
  903. }
  904. #if !(NET40 || NET35 || NET20 || PORTABLE40)
  905. public class PopulateReadOnlyTestClass
  906. {
  907. public IList<int> NonReadOnlyList { get; set; }
  908. public IDictionary<string, int> NonReadOnlyDictionary { get; set; }
  909. public IList<int> Array { get; set; }
  910. public IList<int> List { get; set; }
  911. public IDictionary<string, int> Dictionary { get; set; }
  912. public IReadOnlyCollection<int> IReadOnlyCollection { get; set; }
  913. public ReadOnlyCollection<int> ReadOnlyCollection { get; set; }
  914. public IReadOnlyList<int> IReadOnlyList { get; set; }
  915. public IReadOnlyDictionary<string, int> IReadOnlyDictionary { get; set; }
  916. public ReadOnlyDictionary<string, int> ReadOnlyDictionary { get; set; }
  917. public PopulateReadOnlyTestClass()
  918. {
  919. NonReadOnlyList = new List<int> { 1 };
  920. NonReadOnlyDictionary = new Dictionary<string, int> { { "first", 2 } };
  921. Array = new[] { 3 };
  922. List = new ReadOnlyCollection<int>(new[] { 4 });
  923. Dictionary = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> { { "first", 5 } });
  924. IReadOnlyCollection = new ReadOnlyCollection<int>(new[] { 6 });
  925. ReadOnlyCollection = new ReadOnlyCollection<int>(new[] { 7 });
  926. IReadOnlyList = new ReadOnlyCollection<int>(new[] { 8 });
  927. IReadOnlyDictionary = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> { { "first", 9 } });
  928. ReadOnlyDictionary = new ReadOnlyDictionary<string, int>(new Dictionary<string, int> { { "first", 10 } });
  929. }
  930. }
  931. [Test]
  932. public void SerializeReadOnlyCollections()
  933. {
  934. PopulateReadOnlyTestClass c1 = new PopulateReadOnlyTestClass();
  935. string json = JsonConvert.SerializeObject(c1, Formatting.Indented);
  936. StringAssert.AreEqual(@"{
  937. ""NonReadOnlyList"": [
  938. 1
  939. ],
  940. ""NonReadOnlyDictionary"": {
  941. ""first"": 2
  942. },
  943. ""Array"": [
  944. 3
  945. ],
  946. ""List"": [
  947. 4
  948. ],
  949. ""Dictionary"": {
  950. ""first"": 5
  951. },
  952. ""IReadOnlyCollection"": [
  953. 6
  954. ],
  955. ""ReadOnlyCollection"": [
  956. 7
  957. ],
  958. ""IReadOnlyList"": [
  959. 8
  960. ],
  961. ""IReadOnlyDictionary"": {
  962. ""first"": 9
  963. },
  964. ""ReadOnlyDictionary"": {
  965. ""first"": 10
  966. }
  967. }", json);
  968. }
  969. [Test]
  970. public void PopulateReadOnlyCollections()
  971. {
  972. string json = @"{
  973. ""NonReadOnlyList"": [
  974. 11
  975. ],
  976. ""NonReadOnlyDictionary"": {
  977. ""first"": 12
  978. },
  979. ""Array"": [
  980. 13
  981. ],
  982. ""List"": [
  983. 14
  984. ],
  985. ""Dictionary"": {
  986. ""first"": 15
  987. },
  988. ""IReadOnlyCollection"": [
  989. 16
  990. ],
  991. ""ReadOnlyCollection"": [
  992. 17
  993. ],
  994. ""IReadOnlyList"": [
  995. 18
  996. ],
  997. ""IReadOnlyDictionary"": {
  998. ""first"": 19
  999. },
  1000. ""ReadOnlyDictionary"": {
  1001. ""first"": 20
  1002. }
  1003. }";
  1004. var c2 = JsonConvert.DeserializeObject<PopulateReadOnlyTestClass>(json);
  1005. Assert.AreEqual(1, c2.NonReadOnlyDictionary.Count);
  1006. Assert.AreEqual(12, c2.NonReadOnlyDictionary["first"]);
  1007. Assert.AreEqual(2, c2.NonReadOnlyList.Count);
  1008. Assert.AreEqual(1, c2.NonReadOnlyList[0]);
  1009. Assert.AreEqual(11, c2.NonReadOnlyList[1]);
  1010. Assert.AreEqual(1, c2.Array.Count);
  1011. Assert.AreEqual(13, c2.Array[0]);
  1012. }
  1013. #endif
  1014. [Test]
  1015. public void SerializeArray2D()
  1016. {
  1017. Array2D aa = new Array2D();
  1018. aa.Before = "Before!";
  1019. aa.After = "After!";
  1020. aa.Coordinates = new[,] { { 1, 1 }, { 1, 2 }, { 2, 1 }, { 2, 2 } };
  1021. string json = JsonConvert.SerializeObject(aa);
  1022. Assert.AreEqual(@"{""Before"":""Before!"",""Coordinates"":[[1,1],[1,2],[2,1],[2,2]],""After"":""After!""}", json);
  1023. }
  1024. [Test]
  1025. public void SerializeArray3D()
  1026. {
  1027. Array3D aa = new Array3D();
  1028. aa.Before = "Before!";
  1029. aa.After = "After!";
  1030. aa.Coordinates = new[,,] { { { 1, 1, 1 }, { 1, 1, 2 } }, { { 1, 2, 1 }, { 1, 2, 2 } }, { { 2, 1, 1 }, { 2, 1, 2 } }, { { 2, 2, 1 }, { 2, 2, 2 } } };
  1031. string json = JsonConvert.SerializeObject(aa);
  1032. Assert.AreEqual(@"{""Before"":""Before!"",""Coordinates"":[[[1,1,1],[1,1,2]],[[1,2,1],[1,2,2]],[[2,1,1],[2,1,2]],[[2,2,1],[2,2,2]]],""After"":""After!""}", json);
  1033. }
  1034. [Test]
  1035. public void SerializeArray3DWithConverter()
  1036. {
  1037. Array3DWithConverter aa = new Array3DWithConverter();
  1038. aa.Before = "Before!";
  1039. aa.After = "After!";
  1040. aa.Coordinates = new[,,] { { { 1, 1, 1 }, { 1, 1, 2 } }, { { 1, 2, 1 }, { 1, 2, 2 } }, { { 2, 1, 1 }, { 2, 1, 2 } }, { { 2, 2, 1 }, { 2, 2, 2 } } };
  1041. string json = JsonConvert.SerializeObject(aa, Formatting.Indented);
  1042. StringAssert.AreEqual(@"{
  1043. ""Before"": ""Before!"",
  1044. ""Coordinates"": [
  1045. [
  1046. [
  1047. 1.0,
  1048. 1.0,
  1049. 1.0
  1050. ],
  1051. [
  1052. 1.0,
  1053. 1.0,
  1054. 2.0
  1055. ]
  1056. ],
  1057. [
  1058. [
  1059. 1.0,
  1060. 2.0,
  1061. 1.0
  1062. ],
  1063. [
  1064. 1.0,
  1065. 2.0,
  1066. 2.0
  1067. ]
  1068. ],
  1069. [
  1070. [
  1071. 2.0,
  1072. 1.0,
  1073. 1.0
  1074. ],
  1075. [
  1076. 2.0,
  1077. 1.0,
  1078. 2.0
  1079. ]
  1080. ],
  1081. [
  1082. [
  1083. 2.0,
  1084. 2.0,
  1085. 1.0
  1086. ],
  1087. [
  1088. 2.0,
  1089. 2.0,
  1090. 2.0
  1091. ]
  1092. ]
  1093. ],
  1094. ""After"": ""After!""
  1095. }", json);
  1096. }
  1097. [Test]
  1098. public void DeserializeArray3DWithConverter()
  1099. {
  1100. string json = @"{
  1101. ""Before"": ""Before!"",
  1102. ""Coordinates"": [
  1103. [
  1104. [
  1105. 1.0,
  1106. 1.0,
  1107. 1.0
  1108. ],
  1109. [
  1110. 1.0,
  1111. 1.0,
  1112. 2.0
  1113. ]
  1114. ],
  1115. [
  1116. [
  1117. 1.0,
  1118. 2.0,
  1119. 1.0
  1120. ],
  1121. [
  1122. 1.0,
  1123. 2.0,
  1124. 2.0
  1125. ]
  1126. ],
  1127. [
  1128. [
  1129. 2.0,
  1130. 1.0,
  1131. 1.0
  1132. ],
  1133. [
  1134. 2.0,
  1135. 1.0,
  1136. 2.0
  1137. ]
  1138. ],
  1139. [
  1140. [
  1141. 2.0,
  1142. 2.0,
  1143. 1.0
  1144. ],
  1145. [
  1146. 2.0,
  1147. 2.0,
  1148. 2.0
  1149. ]
  1150. ]
  1151. ],
  1152. ""After"": ""After!""
  1153. }";
  1154. Array3DWithConverter aa = JsonConvert.DeserializeObject<Array3DWithConverter>(json);
  1155. Assert.AreEqual("Before!", aa.Before);
  1156. Assert.AreEqual("After!", aa.After);
  1157. Assert.AreEqual(4, aa.Coordinates.GetLength(0));
  1158. Assert.AreEqual(2, aa.Coordinates.GetLength(1));
  1159. Assert.AreEqual(3, aa.Coordinates.GetLength(2));
  1160. Assert.AreEqual(1, aa.Coordinates[0, 0, 0]);
  1161. Assert.AreEqual(2, aa.Coordinates[1, 1, 1]);
  1162. }
  1163. [Test]
  1164. public void DeserializeArray2D()
  1165. {
  1166. string json = @"{""Before"":""Before!"",""Coordinates"":[[1,1],[1,2],[2,1],[2,2]],""After"":""After!""}";
  1167. Array2D aa = JsonConvert.DeserializeObject<Array2D>(json);
  1168. Assert.AreEqual("Before!", aa.Before);
  1169. Assert.AreEqual("After!", aa.After);
  1170. Assert.AreEqual(4, aa.Coordinates.GetLength(0));
  1171. Assert.AreEqual(2, aa.Coordinates.GetLength(1));
  1172. Assert.AreEqual(1, aa.Coordinates[0, 0]);
  1173. Assert.AreEqual(2, aa.Coordinates[1, 1]);
  1174. string after = JsonConvert.SerializeObject(aa);
  1175. Assert.AreEqual(json, after);
  1176. }
  1177. [Test]
  1178. public void DeserializeArray2D_WithTooManyItems()
  1179. {
  1180. string json = @"{""Before"":""Before!"",""Coordinates"":[[1,1],[1,2,3],[2,1],[2,2]],""After"":""After!""}";
  1181. ExceptionAssert.Throws<Exception>(() => JsonConvert.DeserializeObject<Array2D>(json), "Cannot deserialize non-cubical array as multidimensional array.");
  1182. }
  1183. [Test]
  1184. public void DeserializeArray2D_WithTooFewItems()
  1185. {
  1186. string json = @"{""Before"":""Before!"",""Coordinates"":[[1,1],[1],[2,1],[2,2]],""After"":""After!""}";
  1187. ExceptionAssert.Throws<Exception>(() => JsonConvert.DeserializeObject<Array2D>(json), "Cannot deserialize non-cubical array as multidimensional array.");
  1188. }
  1189. [Test]
  1190. public void DeserializeArray3D()
  1191. {
  1192. string json = @"{""Before"":""Before!"",""Coordinates"":[[[1,1,1],[1,1,2]],[[1,2,1],[1,2,2]],[[2,1,1],[2,1,2]],[[2,2,1],[2,2,2]]],""After"":""After!""}";
  1193. Array3D aa = JsonConvert.DeserializeObject<Array3D>(json);
  1194. Assert.AreEqual("Before!", aa.Before);
  1195. Assert.AreEqual("After!", aa.After);
  1196. Assert.AreEqual(4, aa.Coordinates.GetLength(0));
  1197. Assert.AreEqual(2, aa.Coordinates.GetLength(1));
  1198. Assert.AreEqual(3, aa.Coordinates.GetLength(2));
  1199. Assert.AreEqual(1, aa.Coordinates[0, 0, 0]);
  1200. Assert.AreEqual(2, aa.Coordinates[1, 1, 1]);
  1201. string after = JsonConvert.SerializeObject(aa);
  1202. Assert.AreEqual(json, after);
  1203. }
  1204. [Test]
  1205. public void DeserializeArray3D_WithTooManyItems()
  1206. {
  1207. string json = @"{""Before"":""Before!"",""Coordinates"":[[[1,1,1],[1,1,2,1]],[[1,2,1],[1,2,2]],[[2,1,1],[2,1,2]],[[2,2,1],[2,2,2]]],""After"":""After!""}";
  1208. ExceptionAssert.Throws<Exception>(() => JsonConvert.DeserializeObject<Array3D>(json), "Cannot deserialize non-cubical array as multidimensional array.");
  1209. }
  1210. [Test]
  1211. public void DeserializeArray3D_WithBadItems()
  1212. {
  1213. string json = @"{""Before"":""Before!"",""Coordinates"":[[[1,1,1],[1,1,2]],[[1,2,1],[1,2,2]],[[2,1,1],[2,1,2]],[[2,2,1],{}]],""After"":""After!""}";
  1214. ExceptionAssert.Throws<JsonSerializationException>(() => JsonConvert.DeserializeObject<Array3D>(json), "Unexpected token when deserializing multidimensional array: StartObject. Path 'Coordinates[3][1]', line 1, position 99.");
  1215. }
  1216. [Test]
  1217. public void DeserializeArray3D_WithTooFewItems()
  1218. {
  1219. string json = @"{""Before"":""Before!"",""Coordinates"":[[[1,1,1],[1,1]],[[1,2,1],[1,2,2]],[[2,1,1],[2,1,2]],[[2,2,1],[2,2,2]]],""After"":""After!""}";
  1220. ExceptionAssert.Throws<Exception>(() => JsonConvert.DeserializeObject<Array3D>(json), "Cannot deserialize non-cubical array as multidimensional array.");
  1221. }
  1222. [Test]
  1223. public void SerializeEmpty3DArray()
  1224. {
  1225. Array3D aa = new Array3D();
  1226. aa.Before = "Before!";
  1227. aa.After = "After!";
  1228. aa.Coordinates = new int[0, 0, 0];
  1229. string json = JsonConvert.SerializeObject(aa);
  1230. Assert.AreEqual(@"{""Before"":""Before!"",""Coordinates"":[],""After"":""After!""}", json);
  1231. }
  1232. [Test]
  1233. public void DeserializeEmpty3DArray()
  1234. {
  1235. string json = @"{""Before"":""Before!"",""Coordinates"":[],""After"":""After!""}";
  1236. Array3D aa = JsonConvert.DeserializeObject<Array3D>(json);
  1237. Assert.AreEqual("Before!", aa.Before);
  1238. Assert.AreEqual("After!", aa.After);
  1239. Assert.AreEqual(0, aa.Coordinates.GetLength(0));
  1240. Assert.AreEqual(0, aa.Coordinates.GetLength(1));
  1241. Assert.AreEqual(0, aa.Coordinates.GetLength(2));
  1242. string after = JsonConvert.SerializeObject(aa);
  1243. Assert.AreEqual(json, after);
  1244. }
  1245. [Test]
  1246. public void DeserializeIncomplete3DArray()
  1247. {
  1248. string json = @"{""Before"":""Before!"",""Coordinates"":[/*hi*/[/*hi*/[1/*hi*/,/*hi*/1/*hi*/,1]/*hi*/,/*hi*/[1,1";
  1249. ExceptionAssert.Throws<JsonException>(() => JsonConvert.DeserializeObject<Array3D>(json));
  1250. }
  1251. [Test]
  1252. public void DeserializeIncompleteNotTopLevel3DArray()
  1253. {
  1254. string json = @"{""Before"":""Before!"",""Coordinates"":[/*hi*/[/*hi*/";
  1255. ExceptionAssert.Throws<JsonException>(() => JsonConvert.DeserializeObject<Array3D>(json));
  1256. }
  1257. [Test]
  1258. public void DeserializeNull3DArray()
  1259. {
  1260. string json = @"{""Before"":""Before!"",""Coordinates"":null,""After"":""After!""}";
  1261. Array3D aa = JsonConvert.DeserializeObject<Array3D>(json);
  1262. Assert.AreEqual("Before!", aa.Before);
  1263. Assert.AreEqual("After!", aa.After);
  1264. Assert.AreEqual(null, aa.Coordinates);
  1265. string after = JsonConvert.SerializeObject(aa);
  1266. Assert.AreEqual(json, after);
  1267. }
  1268. [Test]
  1269. public void DeserializeSemiEmpty3DArray()
  1270. {
  1271. string json = @"{""Before"":""Before!"",""Coordinates"":[[]],""After"":""After!""}";
  1272. Array3D aa = JsonConvert.DeserializeObject<Array3D>(json);
  1273. Assert.AreEqual("Before!", aa.Before);
  1274. Assert.AreEqual("After!", aa.After);
  1275. Assert.AreEqual(1, aa.Coordinates.GetLength(0));
  1276. Assert.AreEqual(0, aa.Coordinates.GetLength(1));
  1277. Assert.AreEqual(0, aa.Coordinates.GetLength(2));
  1278. string after = JsonConvert.SerializeObject(aa);
  1279. Assert.AreEqual(json, after);
  1280. }
  1281. [Test]
  1282. public void SerializeReferenceTracked3DArray()
  1283. {
  1284. Event1 e1 = new Event1
  1285. {
  1286. EventName = "EventName!"
  1287. };
  1288. Event1[,] array1 = new[,] { { e1, e1 }, { e1, e1 } };
  1289. IList<Event1[,]> values1 = new List<Event1[,]>
  1290. {
  1291. array1,
  1292. array1
  1293. };
  1294. string json = JsonConvert.SerializeObject(values1, new JsonSerializerSettings
  1295. {
  1296. PreserveReferencesHandling = PreserveReferencesHandling.All,
  1297. Formatting = Formatting.Indented
  1298. });
  1299. StringAssert.AreEqual(@"{
  1300. ""$id"": ""1"",
  1301. ""$values"": [
  1302. {
  1303. ""$id"": ""2"",
  1304. ""$values"": [
  1305. [
  1306. {
  1307. ""$id"": ""3"",
  1308. ""EventName"": ""EventName!"",
  1309. ""Venue"": null,
  1310. ""Performances"": null
  1311. },
  1312. {
  1313. ""$ref"": ""3""
  1314. }
  1315. ],
  1316. [
  1317. {
  1318. ""$ref"": ""3""
  1319. },
  1320. {
  1321. ""$ref"": ""3""
  1322. }
  1323. ]
  1324. ]
  1325. },
  1326. {
  1327. ""$ref"": ""2""
  1328. }
  1329. ]
  1330. }", json);
  1331. }
  1332. [Test]
  1333. public void SerializeTypeName3DArray()
  1334. {
  1335. Event1 e1 = new Event1
  1336. {
  1337. EventName = "EventName!"
  1338. };
  1339. Event1[,] array1 = new[,] { { e1, e1 }, { e1, e1 } };
  1340. IList<Event1[,]> values1 = new List<Event1[,]>
  1341. {
  1342. array1,
  1343. array1
  1344. };
  1345. string json = JsonConvert.SerializeObject(values1, new JsonSerializerSettings
  1346. {
  1347. TypeNameHandling = TypeNameHandling.All,
  1348. Formatting = Formatting.Indented
  1349. });
  1350. StringAssert.AreEqual(@"{
  1351. ""$type"": """ + ReflectionUtils.GetTypeName(typeof(List<Event1[,]>), 0, DefaultSerializationBinder.Instance) + @""",
  1352. ""$values"": [
  1353. {
  1354. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1[,], Newtonsoft.Json.Tests"",
  1355. ""$values"": [
  1356. [
  1357. {
  1358. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1359. ""EventName"": ""EventName!"",
  1360. ""Venue"": null,
  1361. ""Performances"": null
  1362. },
  1363. {
  1364. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1365. ""EventName"": ""EventName!"",
  1366. ""Venue"": null,
  1367. ""Performances"": null
  1368. }
  1369. ],
  1370. [
  1371. {
  1372. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1373. ""EventName"": ""EventName!"",
  1374. ""Venue"": null,
  1375. ""Performances"": null
  1376. },
  1377. {
  1378. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1379. ""EventName"": ""EventName!"",
  1380. ""Venue"": null,
  1381. ""Performances"": null
  1382. }
  1383. ]
  1384. ]
  1385. },
  1386. {
  1387. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1[,], Newtonsoft.Json.Tests"",
  1388. ""$values"": [
  1389. [
  1390. {
  1391. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1392. ""EventName"": ""EventName!"",
  1393. ""Venue"": null,
  1394. ""Performances"": null
  1395. },
  1396. {
  1397. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1398. ""EventName"": ""EventName!"",
  1399. ""Venue"": null,
  1400. ""Performances"": null
  1401. }
  1402. ],
  1403. [
  1404. {
  1405. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1406. ""EventName"": ""EventName!"",
  1407. ""Venue"": null,
  1408. ""Performances"": null
  1409. },
  1410. {
  1411. ""$type"": ""Newtonsoft.Json.Tests.TestObjects.Events.Event1, Newtonsoft.Json.Tests"",
  1412. ""EventName"": ""EventName!"",
  1413. ""Venue"": null,
  1414. ""Performances"": null
  1415. }
  1416. ]
  1417. ]
  1418. }
  1419. ]
  1420. }", json);
  1421. IList<Event1[,]> values2 = (IList<Event1[,]>)JsonConvert.DeserializeObject(json, new JsonSerializerSettings
  1422. {
  1423. TypeNameHandling = TypeNameHandling.All
  1424. });
  1425. Assert.AreEqual(2, values2.Count);
  1426. Assert.AreEqual("EventName!", values2[0][0, 0].EventName);
  1427. }
  1428. [Test]
  1429. public void PrimitiveValuesInObjectArray()
  1430. {
  1431. string json = @"{""action"":""Router"",""method"":""Navigate"",""data"":[""dashboard"",null],""type"":""rpc"",""tid"":2}";
  1432. ObjectArrayPropertyTest o = JsonConvert.DeserializeObject<ObjectArrayPropertyTest>(json);
  1433. Assert.AreEqual("Router", o.Action);
  1434. Assert.AreEqual("Navigate", o.Method);
  1435. Assert.AreEqual(2, o.Data.Length);
  1436. Assert.AreEqual("dashboard", o.Data[0]);
  1437. Assert.AreEqual(null, o.Data[1]);
  1438. }
  1439. [Test]
  1440. public void ComplexValuesInObjectArray()
  1441. {
  1442. string json = @"{""action"":""Router"",""method"":""Navigate"",""data"":[""dashboard"",[""id"", 1, ""teststring"", ""test""],{""one"":1}],""type"":""rpc"",""tid"":2}";
  1443. ObjectArrayPropertyTest o = JsonConvert.DeserializeObject<ObjectArrayPropertyTest>(json);
  1444. Assert.AreEqual("Router", o.Action);
  1445. Assert.AreEqual("Navigate", o.Method);
  1446. Assert.AreEqual(3, o.Data.Length);
  1447. Assert.AreEqual("dashboard", o.Data[0]);
  1448. CustomAssert.IsInstanceOfType(typeof(JArray), o.Data[1]);
  1449. Assert.AreEqual(4, ((JArray)o.Data[1]).Count);
  1450. CustomAssert.IsInstanceOfType(typeof(JObject), o.Data[2]);
  1451. Assert.AreEqual(1, ((JObject)o.Data[2]).Count);
  1452. Assert.AreEqual(1, (int)((JObject)o.Data[2])["one"]);
  1453. }
  1454. #if !(DNXCORE50)
  1455. [Test]
  1456. public void SerializeArrayAsArrayList()
  1457. {
  1458. string jsonText = @"[3, ""somestring"",[1,2,3],{}]";
  1459. ArrayList o = JsonConvert.DeserializeObject<ArrayList>(jsonText);
  1460. Assert.AreEqual(4, o.Count);
  1461. Assert.AreEqual(3, ((JArray)o[2]).Count);
  1462. Assert.AreEqual(0, ((JObject)o[3]).Count);
  1463. }
  1464. #endif
  1465. [Test]
  1466. public void SerializeMemberGenericList()
  1467. {
  1468. Name name = new Name("The Idiot in Next To Me");
  1469. PhoneNumber p1 = new PhoneNumber("555-1212");
  1470. PhoneNumber p2 = new PhoneNumber("444-1212");
  1471. name.pNumbers.Add(p1);
  1472. name.pNumbers.Add(p2);
  1473. string json = JsonConvert.SerializeObject(name, Formatting.Indented);
  1474. StringAssert.AreEqual(@"{
  1475. ""personsName"": ""The Idiot in Next To Me"",
  1476. ""pNumbers"": [
  1477. {
  1478. ""phoneNumber"": ""555-1212""
  1479. },
  1480. {
  1481. ""phoneNumber"": ""444-1212""
  1482. }
  1483. ]
  1484. }", json);
  1485. Name newName = JsonConvert.DeserializeObject<Name>(json);
  1486. Assert.AreEqual("The Idiot in Next To Me", newName.personsName);
  1487. // not passed in as part of the constructor but assigned to pNumbers property
  1488. Assert.AreEqual(2, newName.pNumbers.Count);
  1489. Assert.AreEqual("555-1212", newName.pNumbers[0].phoneNumber);
  1490. Assert.AreEqual("444-1212", newName.pNumbers[1].phoneNumber);
  1491. }
  1492. [Test]
  1493. public void CustomCollectionSerialization()
  1494. {
  1495. ProductCollection collection = new ProductCollection()
  1496. {
  1497. new Product() { Name = "Test1" },
  1498. new Product() { Name = "Test2" },
  1499. new Product() { Name = "Test3" }
  1500. };
  1501. JsonSerializer jsonSerializer = new JsonSerializer();
  1502. jsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  1503. StringWriter sw = new StringWriter();
  1504. jsonSerializer.Serialize(sw, collection);
  1505. Assert.AreEqual(@"[{""Name"":""Test1"",""ExpiryDate"":""2000-01-01T00:00:00Z"",""Price"":0.0,""Sizes"":null},{""Name"":""Test2"",""ExpiryDate"":""2000-01-01T00:00:00Z"",""Price"":0.0,""Sizes"":null},{""Name"":""Test3"",""ExpiryDate"":""2000-01-01T00:00:00Z"",""Price"":0.0,""Sizes"":null}]",
  1506. sw.GetStringBuilder().ToString());
  1507. ProductCollection collectionNew = (ProductCollection)jsonSerializer.Deserialize(new JsonTextReader(new StringReader(sw.GetStringBuilder().ToString())), typeof(ProductCollection));
  1508. CollectionAssert.AreEqual(collection, collectionNew);
  1509. }
  1510. [Test]
  1511. public void GenericCollectionInheritance()
  1512. {
  1513. string json;
  1514. GenericClass<GenericItem<string>, string> foo1 = new GenericClass<GenericItem<string>, string>();
  1515. foo1.Items.Add(new GenericItem<string> { Value = "Hello" });
  1516. json = JsonConvert.SerializeObject(new { selectList = foo1 });
  1517. Assert.AreEqual(@"{""selectList"":[{""Value"":""Hello""}]}", json);
  1518. GenericClass<NonGenericItem, string> foo2 = new GenericClass<NonGenericItem, string>();
  1519. foo2.Items.Add(new NonGenericItem { Value = "Hello" });
  1520. json = JsonConvert.SerializeObject(new { selectList = foo2 });
  1521. Assert.AreEqual(@"{""selectList"":[{""Value"":""Hello""}]}", json);
  1522. NonGenericClass foo3 = new NonGenericClass();
  1523. foo3.Items.Add(new NonGenericItem { Value = "Hello" });
  1524. json = JsonConvert.SerializeObject(new { selectList = foo3 });
  1525. Assert.AreEqual(@"{""selectList"":[{""Value"":""Hello""}]}", json);
  1526. }
  1527. [Test]
  1528. public void InheritedListSerialize()
  1529. {
  1530. Article a1 = new Article("a1");
  1531. Article a2 = new Article("a2");
  1532. ArticleCollection articles1 = new ArticleCollection();
  1533. articles1.Add(a1);
  1534. articles1.Add(a2);
  1535. string jsonText = JsonConvert.SerializeObject(articles1);
  1536. ArticleCollection articles2 = JsonConvert.DeserializeObject<ArticleCollection>(jsonText);
  1537. Assert.AreEqual(articles1.Count, articles2.Count);
  1538. Assert.AreEqual(articles1[0].Name, articles2[0].Name);
  1539. }
  1540. [Test]
  1541. public void ReadOnlyCollectionSerialize()
  1542. {
  1543. ReadOnlyCollection<int> r1 = new ReadOnlyCollection<int>(new int[] { 0, 1, 2, 3, 4 });
  1544. string jsonText = JsonConvert.SerializeObject(r1);
  1545. Assert.AreEqual("[0,1,2,3,4]", jsonText);
  1546. ReadOnlyCollection<int> r2 = JsonConvert.DeserializeObject<ReadOnlyCollection<int>>(jsonText);
  1547. CollectionAssert.AreEqual(r1, r2);
  1548. }
  1549. [Test]
  1550. public void SerializeGenericList()
  1551. {
  1552. Product p1 = new Product
  1553. {
  1554. Name = "Product 1",
  1555. Price = 99.95m,
  1556. ExpiryDate = new DateTime(2000, 12, 29, 0, 0, 0, DateTimeKind.Utc),
  1557. };
  1558. Product p2 = new Product
  1559. {
  1560. Name = "Product 2",
  1561. Price = 12.50m,
  1562. ExpiryDate = new DateTime(2009, 7, 31, 0, 0, 0, DateTimeKind.Utc),
  1563. };
  1564. List<Product> products = new List<Product>();
  1565. products.Add(p1);
  1566. products.Add(p2);
  1567. string json = JsonConvert.SerializeObject(products, Formatting.Indented);
  1568. //[
  1569. // {
  1570. // "Name": "Product 1",
  1571. // "ExpiryDate": "\/Date(978048000000)\/",
  1572. // "Price": 99.95,
  1573. // "Sizes": null
  1574. // },
  1575. // {
  1576. // "Name": "Product 2",
  1577. // "ExpiryDate": "\/Date(1248998400000)\/",
  1578. // "Price": 12.50,
  1579. // "Sizes": null
  1580. // }
  1581. //]
  1582. StringAssert.AreEqual(@"[
  1583. {
  1584. ""Name"": ""Product 1"",
  1585. ""ExpiryDate"": ""2000-12-29T00:00:00Z"",
  1586. ""Price"": 99.95,
  1587. ""Sizes"": null
  1588. },
  1589. {
  1590. ""Name"": ""Product 2"",
  1591. ""ExpiryDate"": ""2009-07-31T00:00:00Z"",
  1592. ""Price"": 12.50,
  1593. ""Sizes"": null
  1594. }
  1595. ]", json);
  1596. }
  1597. [Test]
  1598. public void DeserializeGenericList()
  1599. {
  1600. string json = @"[
  1601. {
  1602. ""Name"": ""Product 1"",
  1603. ""ExpiryDate"": ""\/Date(978048000000)\/"",
  1604. ""Price"": 99.95,
  1605. ""Sizes"": null
  1606. },
  1607. {
  1608. ""Name"": ""Product 2"",
  1609. ""ExpiryDate"": ""\/Date(1248998400000)\/"",
  1610. ""Price"": 12.50,
  1611. ""Sizes"": null
  1612. }
  1613. ]";
  1614. List<Product> products = JsonConvert.DeserializeObject<List<Product>>(json);
  1615. Product p1 = products[0];
  1616. Assert.AreEqual(2, products.Count);
  1617. Assert.AreEqual("Product 1", p1.Name);
  1618. }
  1619. #if !(NET40 || NET35 || NET20 || PORTABLE40)
  1620. [Test]
  1621. public void ReadOnlyIntegerList()
  1622. {
  1623. ReadOnlyIntegerList l = new ReadOnlyIntegerList(new List<int>
  1624. {
  1625. 1,
  1626. 2,
  1627. 3,
  1628. int.MaxValue
  1629. });
  1630. string json = JsonConvert.SerializeObject(l, Formatting.Indented);
  1631. StringAssert.AreEqual(@"[
  1632. 1,
  1633. 2,
  1634. 3,
  1635. 2147483647
  1636. ]", json);
  1637. }
  1638. #endif
  1639. #if !DNXCORE50
  1640. [Test]
  1641. public void EmptyStringInHashtableIsDeserialized()
  1642. {
  1643. string externalJson = @"{""$type"":""System.Collections.Hashtable, mscorlib"",""testkey"":""""}";
  1644. JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
  1645. JsonConvert.SerializeObject(new Hashtable { { "testkey", "" } }, settings);
  1646. Hashtable deserializeTest2 = JsonConvert.DeserializeObject<Hashtable>(externalJson, settings);
  1647. Assert.AreEqual(deserializeTest2["testkey"], "");
  1648. }
  1649. #endif
  1650. [Test]
  1651. public void DeserializeCollectionWithConstructorArrayArgument()
  1652. {
  1653. var v = new ReadOnlyCollectionWithArrayArgument<double>(new[] { -0.014147478859765236, -0.011419606805541858, -0.010038461483676238 });
  1654. var json = JsonConvert.SerializeObject(v);
  1655. ExceptionAssert.Throws<JsonSerializationException>(() =>
  1656. {
  1657. JsonConvert.DeserializeObject<ReadOnlyCollectionWithArrayArgument<double>>(json);
  1658. }, "Unable to find a constructor to use for type Newtonsoft.Json.Tests.Serialization.ReadOnlyCollectionWithArrayArgument`1[System.Double]. Path '', line 1, position 1.");
  1659. }
  1660. #if !NET20 && !PORTABLE40
  1661. [Test]
  1662. public void NonDefaultConstructor_DuplicateKeyInDictionary_Replace()
  1663. {
  1664. string json = @"{ ""user"":""bpan"", ""Person"":{ ""groups"":""replaced!"", ""domain"":""adm"", ""mail"":""bpan@sdu.dk"", ""sn"":""Pan"", ""gn"":""Benzhi"", ""cn"":""Benzhi Pan"", ""eo"":""BQHLJaVTMr0eWsi1jaIut4Ls/pSuMeNEmsWfWsfKo="", ""guid"":""9A38CE8E5B288942A8DA415CF5E687"", ""employeenumber"":""2674"", ""omk1"":""930"", ""language"":""da"" }, ""XMLResponce"":""<?xml version='1.0' encoding='iso-8859-1' ?>\n<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\n\t<cas:authenticationSuccess>\n\t\t<cas:user>bpan</cas:user>\n\t\t<norEduPerson>\n\t\t\t<groups>FNC-PRI-APP-SUNDB-EDOR-A,FNC-RI-APP-SUB-EDITOR-B</groups>\n\t\t\t<domain>adm</domain>\n\t\t\t<mail>bpan@sdu.dk</mail>\n\t\t\t<sn>Pan</sn>\n\t\t\t<gn>Benzhi</gn>\n\t\t\t<cn>Benzhi Pan</cn>\n\t\t\t<eo>BQHLJaVTMr0eWsi1jaIut4Lsfr/pSuMeNEmsWfWsfKo=</eo>\n\t\t\t<guid>9A38CE8E5B288942A8DA415C2C687</guid>\n\t\t\t<employeenumber>274</employeenumber>\n\t\t\t<omk1>930</omk1>\n\t\t\t<language>da</language>\n\t\t</norEduPerson>\n\t</cas:authenticationSuccess>\n</cas:serviceResponse>\n"", ""Language"":1, ""Groups"":[ ""FNC-PRI-APP-SNDB-EDOR-A"", ""FNC-PI-APP-SUNDB-EDOR-B"" ], ""Domain"":""adm"", ""Mail"":""bpan@sdu.dk"", ""Surname"":""Pan"", ""Givenname"":""Benzhi"", ""CommonName"":""Benzhi Pan"", ""OrganizationName"":null }";
  1665. var result = JsonConvert.DeserializeObject<CASResponce>(json);
  1666. Assert.AreEqual("replaced!", result.Person["groups"]);
  1667. }
  1668. #endif
  1669. [Test]
  1670. public void GenericIListAndOverrideConstructor()
  1671. {
  1672. MyClass deserialized = JsonConvert.DeserializeObject<MyClass>(@"[""apple"", ""monkey"", ""goose""]");
  1673. Assert.AreEqual("apple", deserialized[0]);
  1674. Assert.AreEqual("monkey", deserialized[1]);
  1675. Assert.AreEqual("goose", deserialized[2]);
  1676. }
  1677. public class MyClass : IList<string>
  1678. {
  1679. private List<string> _storage;
  1680. [JsonConstructor]
  1681. private MyClass()
  1682. {
  1683. _storage = new List<string>();
  1684. }
  1685. public MyClass(IEnumerable<string> source)
  1686. {
  1687. _storage = new List<string>(source);
  1688. }
  1689. //Below is generated by VS to implement IList<string>
  1690. public string this[int index]
  1691. {
  1692. get
  1693. {
  1694. return ((IList<string>)_storage)[index];
  1695. }
  1696. set
  1697. {
  1698. ((IList<string>)_storage)[index] = value;
  1699. }
  1700. }
  1701. public int Count
  1702. {
  1703. get
  1704. {
  1705. return ((IList<string>)_storage).Count;
  1706. }
  1707. }
  1708. public bool IsReadOnly
  1709. {
  1710. get
  1711. {
  1712. return ((IList<string>)_storage).IsReadOnly;
  1713. }
  1714. }
  1715. public void Add(string item)
  1716. {
  1717. ((IList<string>)_storage).Add(item);
  1718. }
  1719. public void Clear()
  1720. {
  1721. ((IList<string>)_storage).Clear();
  1722. }
  1723. public bool Contains(string item)
  1724. {
  1725. return ((IList<string>)_storage).Contains(item);
  1726. }
  1727. public void CopyTo(string[] array, int arrayIndex)
  1728. {
  1729. ((IList<string>)_storage).CopyTo(array, arrayIndex);
  1730. }
  1731. public IEnumerator<string> GetEnumerator()
  1732. {
  1733. return ((IList<string>)_storage).GetEnumerator();
  1734. }
  1735. public int IndexOf(string item)
  1736. {
  1737. return ((IList<string>)_storage).IndexOf(item);
  1738. }
  1739. public void Insert(int index, string item)
  1740. {
  1741. ((IList<string>)_storage).Insert(index, item);
  1742. }
  1743. public bool Remove(string item)
  1744. {
  1745. return ((IList<string>)_storage).Remove(item);
  1746. }
  1747. public void RemoveAt(int index)
  1748. {
  1749. ((IList<string>)_storage).RemoveAt(index);
  1750. }
  1751. IEnumerator IEnumerable.GetEnumerator()
  1752. {
  1753. return ((IList<string>)_storage).GetEnumerator();
  1754. }
  1755. }
  1756. }
  1757. #if !NET20 && !PORTABLE40
  1758. public class CASResponce
  1759. {
  1760. //<?xml version='1.0' encoding='iso-8859-1' ?>
  1761. //<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
  1762. // <cas:authenticationSuccess>
  1763. // <cas:user>and</cas:user>
  1764. // <norEduPerson>
  1765. // <groups>IT-service-OD,USR-IT-service,IT-service-udvikling</groups>
  1766. // <domain>adm</domain>
  1767. // <mail>and@sdu.dk</mail>
  1768. // <sn>And</sn>
  1769. // <gn>Anders</gn>
  1770. // <cn>Anders And</cn>
  1771. // <eo>QQT3tKSKjCxQSGsDiR8HTP9L5VsojBvOYyjOu8pwLMA=</eo>
  1772. // <guid>DE423352CC763649B8F2ECF1DA304750</guid>
  1773. // <language>da</language>
  1774. // </norEduPerson>
  1775. // </cas:authenticationSuccess>
  1776. //</cas:serviceResponse>
  1777. // NemID
  1778. //<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
  1779. // <cas:authenticationSuccess>
  1780. // <cas:user>
  1781. // 2903851921
  1782. // </cas:user>
  1783. // </cas:authenticationSuccess>
  1784. //</cas:serviceResponse>
  1785. //WAYF
  1786. //<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
  1787. // <cas:authenticationSuccess>
  1788. // <cas:user>
  1789. // jj@testidp.wayf.dk
  1790. // </cas:user>
  1791. // <norEduPerson>
  1792. // <sn>Jensen</sn>
  1793. // <gn>Jens</gn>
  1794. // <cn>Jens farmer</cn>
  1795. // <eduPersonPrincipalName>jj @testidp.wayf.dk</eduPersonPrincipalName>
  1796. // <mail>jens.jensen @institution.dk</mail>
  1797. // <organizationName>Institution</organizationName>
  1798. // <eduPersonAssurance>2</eduPersonAssurance>
  1799. // <schacPersonalUniqueID>urn:mace:terena.org:schac:personalUniqueID:dk:CPR:0708741234</schacPersonalUniqueID>
  1800. // <eduPersonScopedAffiliation>student @course1.testidp.wayf.dk</eduPersonScopedAffiliation>
  1801. // <eduPersonScopedAffiliation>staff @course1.testidp.wayf.dk</eduPersonScopedAffiliation>
  1802. // <eduPersonScopedAffiliation>staff @course1.testidp.wsayf.dk</eduPersonScopedAffiliation>
  1803. // <preferredLanguage>en</preferredLanguage>
  1804. // <eduPersonEntitlement>test</eduPersonEntitlement>
  1805. // <eduPersonPrimaryAffiliation>student</eduPersonPrimaryAffiliation>
  1806. // <schacCountryOfCitizenship>DK</schacCountryOfCitizenship>
  1807. // <eduPersonTargetedID>WAYF-DK-7a86d1c3b69a9639d7650b64f2eb773bd21a8c6d</eduPersonTargetedID>
  1808. // <schacHomeOrganization>testidp.wayf.dk</schacHomeOrganization>
  1809. // <givenName>Jens</givenName>
  1810. // <o>Institution</o>
  1811. // <idp>https://testbridge.wayf.dk</idp>
  1812. // </norEduPerson>
  1813. // </cas:authenticationSuccess>
  1814. //</cas:serviceResponse>
  1815. public enum ssoLanguage
  1816. {
  1817. Unknown,
  1818. Danish,
  1819. English
  1820. }
  1821. public CASResponce(string xmlResponce)
  1822. {
  1823. this.Domain = "";
  1824. this.Mail = "";
  1825. this.Surname = "";
  1826. this.Givenname = "";
  1827. this.CommonName = "";
  1828. ParseReplyXML(xmlResponce);
  1829. ExtractGroups();
  1830. ExtractLanguage();
  1831. }
  1832. private void ExtractGroups()
  1833. {
  1834. this.Groups = new List<string>();
  1835. if (this.Person.ContainsKey("groups"))
  1836. {
  1837. string groupsString = this.Person["groups"];
  1838. string[] stringList = groupsString.Split(',');
  1839. foreach (string group in stringList)
  1840. {
  1841. this.Groups.Add(group);
  1842. }
  1843. }
  1844. }
  1845. private void ExtractLanguage()
  1846. {
  1847. if (Person.ContainsKey("language"))
  1848. {
  1849. switch (Person["language"].Trim())
  1850. {
  1851. case "da":
  1852. this.Language = ssoLanguage.Danish;
  1853. break;
  1854. case "en":
  1855. this.Language = ssoLanguage.English;
  1856. break;
  1857. default:
  1858. this.Language = ssoLanguage.Unknown;
  1859. break;
  1860. }
  1861. }
  1862. else
  1863. {
  1864. this.Language = ssoLanguage.Unknown;
  1865. }
  1866. }
  1867. private void ParseReplyXML(string xmlString)
  1868. {
  1869. try
  1870. {
  1871. System.Xml.Linq.XDocument xDoc = XDocument.Parse(xmlString);
  1872. var root = xDoc.Root;
  1873. string ns = "http://www.yale.edu/tp/cas";
  1874. XElement auth = root.Element(XName.Get("authenticationSuccess", ns));
  1875. if (auth == null)
  1876. auth = root.Element(XName.Get("authenticationFailure", ns));
  1877. XElement xNodeUser = auth.Element(XName.Get("user", ns));
  1878. XElement eduPers = auth.Element(XName.Get("norEduPerson", ""));
  1879. string casUser = "";
  1880. Dictionary<string, string> eduPerson = new Dictionary<string, string>();
  1881. if (xNodeUser != null)
  1882. {
  1883. casUser = xNodeUser.Value;
  1884. if (eduPers != null)
  1885. {
  1886. foreach (XElement xPersonValue in eduPers.Elements())
  1887. {
  1888. if (!eduPerson.ContainsKey(xPersonValue.Name.LocalName))
  1889. {
  1890. eduPerson.Add(xPersonValue.Name.LocalName, xPersonValue.Value);
  1891. }
  1892. else
  1893. {
  1894. eduPerson[xPersonValue.Name.LocalName] = eduPerson[xPersonValue.Name.LocalName] + ";" + xPersonValue.Value;
  1895. }
  1896. }
  1897. }
  1898. }
  1899. if (casUser.Trim() != "")
  1900. {
  1901. this.user = casUser;
  1902. }
  1903. if (eduPerson.ContainsKey("domain"))
  1904. this.Domain = eduPerson["domain"];
  1905. if (eduPerson.ContainsKey("organizationName"))
  1906. this.OrganizationName = eduPerson["organizationName"];
  1907. if (eduPerson.ContainsKey("mail"))
  1908. this.Mail = eduPerson["mail"];
  1909. if (eduPerson.ContainsKey("sn"))
  1910. this.Surname = eduPerson["sn"];
  1911. if (eduPerson.ContainsKey("gn"))
  1912. this.Givenname = eduPerson["gn"];
  1913. if (eduPerson.ContainsKey("cn"))
  1914. this.CommonName = eduPerson["cn"];
  1915. this.Person = eduPerson;
  1916. this.XMLResponce = xmlString;
  1917. }
  1918. catch
  1919. {
  1920. this.user = "";
  1921. }
  1922. }
  1923. /// <summary>
  1924. /// Fast felt der altid findes.
  1925. /// </summary>
  1926. public string user { get; private set; }
  1927. /// <summary>
  1928. /// Person type som dictionary indeholdende de ekstra informationer returneret ved login.
  1929. /// </summary>
  1930. public Dictionary<string, string> Person { get; private set; }
  1931. /// <summary>
  1932. /// Den oprindelige xml returneret fra CAS.
  1933. /// </summary>
  1934. public string XMLResponce { get; private set; }
  1935. /// <summary>
  1936. /// Det sprog der benyttes i SSO. Muligheder er da eller en.
  1937. /// </summary>
  1938. public ssoLanguage Language { get; private set; }
  1939. /// <summary>
  1940. /// Liste af grupper som man er medlem af. Kun udvalgt iblandt dem der blev puttet ind i systemet.
  1941. /// </summary>
  1942. public List<string> Groups { get; private set; }
  1943. public string Domain { get; private set; }
  1944. public string Mail { get; private set; }
  1945. public string Surname { get; private set; }
  1946. public string Givenname { get; private set; }
  1947. public string CommonName { get; private set; }
  1948. public string OrganizationName { get; private set; }
  1949. }
  1950. #endif
  1951. public class ReadOnlyCollectionWithArrayArgument<T> : IList<T>
  1952. {
  1953. private readonly IList<T> _values;
  1954. public ReadOnlyCollectionWithArrayArgument(T[] args)
  1955. {
  1956. _values = args ?? (IList<T>)new List<T>();
  1957. }
  1958. public IEnumerator<T> GetEnumerator()
  1959. {
  1960. return _values.GetEnumerator();
  1961. }
  1962. IEnumerator IEnumerable.GetEnumerator()
  1963. {
  1964. return _values.GetEnumerator();
  1965. }
  1966. public void Add(T item)
  1967. {
  1968. throw new NotImplementedException();
  1969. }
  1970. public void Clear()
  1971. {
  1972. throw new NotImplementedException();
  1973. }
  1974. public bool Contains(T item)
  1975. {
  1976. throw new NotImplementedException();
  1977. }
  1978. public void CopyTo(T[] array, int arrayIndex)
  1979. {
  1980. throw new NotImplementedException();
  1981. }
  1982. public bool Remove(T item)
  1983. {
  1984. throw new NotImplementedException();
  1985. }
  1986. public int Count { get; }
  1987. public bool IsReadOnly { get; }
  1988. public int IndexOf(T item)
  1989. {
  1990. throw new NotImplementedException();
  1991. }
  1992. public void Insert(int index, T item)
  1993. {
  1994. throw new NotImplementedException();
  1995. }
  1996. public void RemoveAt(int index)
  1997. {
  1998. throw new NotImplementedException();
  1999. }
  2000. public T this[int index]
  2001. {
  2002. get { throw new NotImplementedException(); }
  2003. set { throw new NotImplementedException(); }
  2004. }
  2005. }
  2006. #if !(NET40 || NET35 || NET20 || PORTABLE40)
  2007. public class ReadOnlyIntegerList : IReadOnlyCollection<int>
  2008. {
  2009. private readonly List<int> _list;
  2010. public ReadOnlyIntegerList(List<int> l)
  2011. {
  2012. _list = l;
  2013. }
  2014. public int Count
  2015. {
  2016. get { return _list.Count; }
  2017. }
  2018. public IEnumerator<int> GetEnumerator()
  2019. {
  2020. return _list.GetEnumerator();
  2021. }
  2022. IEnumerator IEnumerable.GetEnumerator()
  2023. {
  2024. return GetEnumerator();
  2025. }
  2026. }
  2027. #endif
  2028. public class Array2D
  2029. {
  2030. public string Before { get; set; }
  2031. public int[,] Coordinates { get; set; }
  2032. public string After { get; set; }
  2033. }
  2034. public class Array3D
  2035. {
  2036. public string Before { get; set; }
  2037. public int[,,] Coordinates { get; set; }
  2038. public string After { get; set; }
  2039. }
  2040. public class Array3DWithConverter
  2041. {
  2042. public string Before { get; set; }
  2043. [JsonProperty(ItemConverterType = typeof(IntToFloatConverter))]
  2044. public int[,,] Coordinates { get; set; }
  2045. public string After { get; set; }
  2046. }
  2047. public class GenericItem<T>
  2048. {
  2049. public T Value { get; set; }
  2050. }
  2051. public class NonGenericItem : GenericItem<string>
  2052. {
  2053. }
  2054. public class GenericClass<T, TValue> : IEnumerable<T>
  2055. where T : GenericItem<TValue>, new()
  2056. {
  2057. public IList<T> Items { get; set; }
  2058. public GenericClass()
  2059. {
  2060. Items = new List<T>();
  2061. }
  2062. public IEnumerator<T> GetEnumerator()
  2063. {
  2064. if (Items != null)
  2065. {
  2066. foreach (T item in Items)
  2067. {
  2068. yield return item;
  2069. }
  2070. }
  2071. else
  2072. {
  2073. yield break;
  2074. }
  2075. }
  2076. IEnumerator IEnumerable.GetEnumerator()
  2077. {
  2078. return GetEnumerator();
  2079. }
  2080. }
  2081. public class NonGenericClass : GenericClass<GenericItem<string>, string>
  2082. {
  2083. }
  2084. public class StringListAppenderConverter : JsonConverter
  2085. {
  2086. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  2087. {
  2088. writer.WriteValue(value);
  2089. }
  2090. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  2091. {
  2092. List<string> existingStrings = (List<string>)existingValue;
  2093. List<string> newStrings = new List<string>(existingStrings);
  2094. reader.Read();
  2095. while (reader.TokenType != JsonToken.EndArray)
  2096. {
  2097. string s = (string)reader.Value;
  2098. newStrings.Add(s);
  2099. reader.Read();
  2100. }
  2101. return newStrings;
  2102. }
  2103. public override bool CanConvert(Type objectType)
  2104. {
  2105. return (objectType == typeof(List<string>));
  2106. }
  2107. }
  2108. public class StringAppenderConverter : JsonConverter
  2109. {
  2110. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  2111. {
  2112. writer.WriteValue(value);
  2113. }
  2114. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  2115. {
  2116. string existingString = (string)existingValue;
  2117. string newString = existingString + (string)reader.Value;
  2118. return newString;
  2119. }
  2120. public override bool CanConvert(Type objectType)
  2121. {
  2122. return (objectType == typeof(string));
  2123. }
  2124. }
  2125. }