2
// Copyright (c) 2007 James Newton-King
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
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
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.
26
#if !(NET35 || NET20 || PORTABLE)
28
using System.Collections.Generic;
32
using Newtonsoft.Json.Linq;
34
using NUnit.Framework;
36
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
37
using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
38
using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
40
using Newtonsoft.Json.Utilities;
41
using System.Globalization;
43
namespace Newtonsoft.Json.Tests.Linq
46
public class DynamicTests : TestFixtureBase
49
public void JObjectPropertyNames()
51
JObject o = new JObject(
52
new JProperty("ChildValue", "blah blah"));
58
Assert.AreEqual(new JValue("A value!"), d.First);
59
Assert.AreEqual("A value!", (string)d.First);
62
Assert.AreEqual(JTokenType.Null, d.First.Type);
64
Assert.IsTrue(d.Remove("First"));
65
Assert.IsNull(d.First);
67
JValue v1 = d.ChildValue;
68
JValue v2 = d["ChildValue"];
69
Assert.AreEqual(v1, v2);
71
JValue newValue1 = new JValue("Blah blah");
72
d.NewValue = newValue1;
73
JValue newValue2 = d.NewValue;
75
Assert.IsTrue(ReferenceEquals(newValue1, newValue2));
79
public void JObjectEnumerator()
81
JObject o = new JObject(
82
new JProperty("ChildValue", "blah blah"));
86
foreach (JProperty value in d)
88
Assert.AreEqual("ChildValue", value.Name);
89
Assert.AreEqual("blah blah", (string)value.Value);
92
foreach (dynamic value in d)
94
Assert.AreEqual("ChildValue", value.Name);
95
Assert.AreEqual("blah blah", (string)value.Value);
100
public void JObjectPropertyNameWithJArray()
102
JObject o = new JObject(
103
new JProperty("ChildValue", "blah blah"));
107
d.First = new JArray();
110
Assert.AreEqual(1, d.First.Count);
114
public void JObjectPropertyNameWithNonToken()
116
ExceptionAssert.Throws<ArgumentException>(
117
"Could not determine JSON object type for type System.String[].",
120
dynamic d = new JObject();
122
d.First = new[] { "One", "II", "3" };
127
public void JObjectMethods()
129
JObject o = new JObject(
130
new JProperty("ChildValue", "blah blah"));
134
d.Add("NewValue", 1);
136
object count = d.Count;
138
Assert.IsNull(count);
139
Assert.IsNull(d["Count"]);
142
Assert.IsTrue(d.TryGetValue("ChildValue", out v));
143
Assert.AreEqual("blah blah", (string)v);
147
public void JValueEquals()
149
JObject o = new JObject(
150
new JProperty("Null", new JValue(null, JTokenType.Null)),
151
new JProperty("Integer", new JValue(1)),
152
new JProperty("Float", new JValue(1.1d)),
153
new JProperty("Decimal", new JValue(1.1m)),
154
new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
155
new JProperty("Boolean", new JValue(true)),
156
new JProperty("String", new JValue("A string lol!")),
157
new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))),
158
new JProperty("Uri", new Uri("http://json.codeplex.com/")),
159
new JProperty("Guid", new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")),
160
new JProperty("TimeSpan", TimeSpan.FromDays(1))
165
Assert.IsTrue(d.Null == d.Null);
166
Assert.IsTrue(d.Null == null);
167
Assert.IsTrue(d.Null == new JValue(null, JTokenType.Null));
168
Assert.IsFalse(d.Null == 1);
170
Assert.IsTrue(d.Integer == d.Integer);
171
Assert.IsTrue(d.Integer > 0);
172
Assert.IsTrue(d.Integer > 0.0m);
173
Assert.IsTrue(d.Integer > 0.0f);
174
Assert.IsTrue(d.Integer > null);
175
Assert.IsTrue(d.Integer >= null);
176
Assert.IsTrue(d.Integer == 1);
177
Assert.IsTrue(d.Integer == 1m);
178
Assert.IsTrue(d.Integer != 1.1f);
179
Assert.IsTrue(d.Integer != 1.1d);
181
Assert.IsTrue(d.Decimal == d.Decimal);
182
Assert.IsTrue(d.Decimal > 0);
183
Assert.IsTrue(d.Decimal > 0.0m);
184
Assert.IsTrue(d.Decimal > 0.0f);
185
Assert.IsTrue(d.Decimal > null);
186
Assert.IsTrue(d.Decimal >= null);
187
Assert.IsTrue(d.Decimal == 1.1);
188
Assert.IsTrue(d.Decimal == 1.1m);
189
Assert.IsTrue(d.Decimal != 1.0f);
190
Assert.IsTrue(d.Decimal != 1.0d);
192
Assert.IsTrue(d.Float == d.Float);
193
Assert.IsTrue(d.Float > 0);
194
Assert.IsTrue(d.Float > 0.0m);
195
Assert.IsTrue(d.Float > 0.0f);
196
Assert.IsTrue(d.Float > null);
197
Assert.IsTrue(d.Float >= null);
198
Assert.IsTrue(d.Float < 2);
199
Assert.IsTrue(d.Float <= 1.1);
200
Assert.IsTrue(d.Float == 1.1);
201
Assert.IsTrue(d.Float == 1.1m);
202
Assert.IsTrue(d.Float != 1.0f);
203
Assert.IsTrue(d.Float != 1.0d);
205
Assert.IsTrue(d.Bytes == d.Bytes);
206
Assert.IsTrue(d.Bytes == Encoding.UTF8.GetBytes("A string lol!"));
207
Assert.IsTrue(d.Bytes == new JValue(Encoding.UTF8.GetBytes("A string lol!")));
209
Assert.IsTrue(d.Uri == d.Uri);
210
Assert.IsTrue(d.Uri == new Uri("http://json.codeplex.com/"));
211
Assert.IsTrue(d.Uri > new Uri("http://abc.org/"));
212
Assert.IsTrue(d.Uri >= new Uri("http://abc.com/"));
213
Assert.IsTrue(d.Uri > null);
214
Assert.IsTrue(d.Uri >= null);
216
Assert.IsTrue(d.Guid == d.Guid);
217
Assert.IsTrue(d.Guid == new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF"));
218
Assert.IsTrue(d.Guid > new Guid("AAAAAAAA-0D80-44F2-BF34-4654156FA7AF"));
219
Assert.IsTrue(d.Guid >= new Guid("AAAAAAAA-0D80-44F2-BF34-4654156FA7AF"));
220
Assert.IsTrue(d.Guid > null);
221
Assert.IsTrue(d.Guid >= null);
223
Assert.IsTrue(d.TimeSpan == d.TimeSpan);
224
Assert.IsTrue(d.TimeSpan == TimeSpan.FromDays(1));
225
Assert.IsTrue(d.TimeSpan > TimeSpan.FromHours(1));
226
Assert.IsTrue(d.TimeSpan >= TimeSpan.FromHours(1));
227
Assert.IsTrue(d.TimeSpan > null);
228
Assert.IsTrue(d.TimeSpan >= null);
232
public void JValueAddition()
234
JObject o = new JObject(
235
new JProperty("Null", new JValue(null, JTokenType.Null)),
236
new JProperty("Integer", new JValue(1)),
237
new JProperty("Float", new JValue(1.1d)),
238
new JProperty("Decimal", new JValue(1.1m)),
239
new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
240
new JProperty("Boolean", new JValue(true)),
241
new JProperty("String", new JValue("A string lol!")),
242
new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))),
243
new JProperty("Uri", new Uri("http://json.codeplex.com/")),
244
new JProperty("Guid", new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")),
245
new JProperty("TimeSpan", TimeSpan.FromDays(1))
252
r = d.String + " LAMO!";
253
Assert.AreEqual("A string lol! LAMO!", (string)r);
255
Assert.AreEqual("A string lol! LAMO! gg", (string)r);
258
Assert.AreEqual("A string lol!", (string)r);
260
Assert.AreEqual("A string lol!", (string)r);
263
Assert.AreEqual(2, (int)r);
265
Assert.AreEqual(4, (int)r);
268
Assert.AreEqual(2.1, (double)r);
270
Assert.AreEqual(4.1, (double)r);
272
r = d.Integer + 1.1d;
273
Assert.AreEqual(2.1m, (decimal)r);
275
Assert.AreEqual(4.1m, (decimal)r);
277
r = d.Integer + null;
278
Assert.AreEqual(null, r.Value);
280
Assert.AreEqual(null, r.Value);
283
Assert.AreEqual(2.1d, (double)r);
285
Assert.AreEqual(4.1d, (double)r);
288
Assert.AreEqual(2.2d, (double)r);
290
Assert.AreEqual(4.2d, (double)r);
293
Assert.AreEqual(2.2m, (decimal)r);
295
Assert.AreEqual(4.2m, (decimal)r);
298
Assert.AreEqual(null, r.Value);
300
Assert.AreEqual(null, r.Value);
303
Assert.AreEqual(2.1m, (decimal)r);
305
Assert.AreEqual(4.1m, (decimal)r);
308
Assert.AreEqual(2.2m, (decimal)r);
310
Assert.AreEqual(4.2m, (decimal)r);
312
r = d.Decimal + 1.1d;
313
Assert.AreEqual(2.2m, (decimal)r);
315
Assert.AreEqual(4.2m, (decimal)r);
317
r = d.Decimal + null;
318
Assert.AreEqual(null, r.Value);
320
Assert.AreEqual(null, r.Value);
325
Assert.AreEqual(0, (int)r);
327
Assert.AreEqual(-2, (int)r);
330
Assert.AreEqual(-0.1d, (double)r, 0.00001);
332
Assert.AreEqual(-2.1d, (double)r);
334
r = d.Integer - 1.1d;
335
Assert.AreEqual(-0.1m, (decimal)r);
337
Assert.AreEqual(-2.1m, (decimal)r);
339
r = d.Integer - null;
340
Assert.AreEqual(null, r.Value);
342
Assert.AreEqual(null, r.Value);
345
Assert.AreEqual(0.1d, (double)r, 0.00001);
347
Assert.AreEqual(-1.9d, (double)r);
350
Assert.AreEqual(0d, (double)r);
352
Assert.AreEqual(-2d, (double)r);
355
Assert.AreEqual(0m, (decimal)r);
357
Assert.AreEqual(-2m, (decimal)r);
360
Assert.AreEqual(null, r.Value);
362
Assert.AreEqual(null, r.Value);
365
Assert.AreEqual(0.1m, (decimal)r);
367
Assert.AreEqual(-1.9m, (decimal)r);
370
Assert.AreEqual(0m, (decimal)r);
372
Assert.AreEqual(-2m, (decimal)r);
374
r = d.Decimal - 1.1d;
375
Assert.AreEqual(0m, (decimal)r);
377
Assert.AreEqual(-2m, (decimal)r);
379
r = d.Decimal - null;
380
Assert.AreEqual(null, r.Value);
382
Assert.AreEqual(null, r.Value);
387
Assert.AreEqual(1, (int)r);
389
Assert.AreEqual(2, (int)r);
392
Assert.AreEqual(1.1d, (double)r);
394
Assert.AreEqual(2.2d, (double)r);
396
r = d.Integer * 1.1d;
397
Assert.AreEqual(1.1m, (decimal)r);
399
Assert.AreEqual(2.2m, (decimal)r);
401
r = d.Integer * null;
402
Assert.AreEqual(null, r.Value);
404
Assert.AreEqual(null, r.Value);
407
Assert.AreEqual(1.1d, (double)r);
409
Assert.AreEqual(2.2d, (double)r);
412
Assert.AreEqual(1.21d, (double)r, 0.00001);
414
Assert.AreEqual(2.42d, (double)r, 0.00001);
417
Assert.AreEqual(1.21m, (decimal)r);
419
Assert.AreEqual(2.42m, (decimal)r);
422
Assert.AreEqual(null, r.Value);
424
Assert.AreEqual(null, r.Value);
427
Assert.AreEqual(1.1m, (decimal)r);
429
Assert.AreEqual(2.2m, (decimal)r);
432
Assert.AreEqual(1.21m, (decimal)r);
434
Assert.AreEqual(2.42m, (decimal)r);
436
r = d.Decimal * 1.1d;
437
Assert.AreEqual(1.21m, (decimal)r);
439
Assert.AreEqual(2.42m, (decimal)r);
441
r = d.Decimal * null;
442
Assert.AreEqual(null, r.Value);
444
Assert.AreEqual(null, r.Value);
449
Assert.AreEqual(1, (int)r);
451
Assert.AreEqual(0, (int)r);
454
Assert.AreEqual(0.9090909090909091d, (double)r);
456
Assert.AreEqual(0.454545454545455d, (double)r, 0.00001);
458
r = d.Integer / 1.1d;
459
Assert.AreEqual(0.909090909090909m, (decimal)r);
461
Assert.AreEqual(0.454545454545454m, (decimal)r);
463
r = d.Integer / null;
464
Assert.AreEqual(null, r.Value);
466
Assert.AreEqual(null, r.Value);
469
Assert.AreEqual(1.1d, (double)r);
471
Assert.AreEqual(0.55d, (double)r);
474
Assert.AreEqual(1d, (double)r, 0.00001);
476
Assert.AreEqual(0.5d, (double)r, 0.00001);
479
Assert.AreEqual(1m, (decimal)r);
481
Assert.AreEqual(0.5m, (decimal)r);
484
Assert.AreEqual(null, r.Value);
486
Assert.AreEqual(null, r.Value);
489
Assert.AreEqual(1.1m, (decimal)r);
491
Assert.AreEqual(0.55m, (decimal)r);
494
Assert.AreEqual(1m, (decimal)r);
496
Assert.AreEqual(0.5m, (decimal)r);
498
r = d.Decimal / 1.1d;
499
Assert.AreEqual(1m, (decimal)r);
501
Assert.AreEqual(0.5m, (decimal)r);
503
r = d.Decimal / null;
504
Assert.AreEqual(null, r.Value);
506
Assert.AreEqual(null, r.Value);
511
public void JValueToString()
513
JObject o = new JObject(
514
new JProperty("Null", new JValue(null, JTokenType.Null)),
515
new JProperty("Integer", new JValue(1)),
516
new JProperty("Float", new JValue(1.1)),
517
new JProperty("DateTime", new JValue(new DateTime(2000, 12, 29, 23, 51, 10, DateTimeKind.Utc))),
518
new JProperty("Boolean", new JValue(true)),
519
new JProperty("String", new JValue("A string lol!")),
520
new JProperty("Bytes", new JValue(Encoding.UTF8.GetBytes("A string lol!"))),
521
new JProperty("Uri", new Uri("http://json.codeplex.com/")),
522
new JProperty("Guid", new Guid("EA27FE1D-0D80-44F2-BF34-4654156FA7AF")),
523
new JProperty("TimeSpan", TimeSpan.FromDays(1))
528
Assert.AreEqual("", d.Null.ToString());
529
Assert.AreEqual("1", d.Integer.ToString());
530
Assert.AreEqual("1.1", d.Float.ToString(CultureInfo.InvariantCulture));
531
Assert.AreEqual("12/29/2000 23:51:10", d.DateTime.ToString(null, CultureInfo.InvariantCulture));
532
Assert.AreEqual("True", d.Boolean.ToString());
533
Assert.AreEqual("A string lol!", d.String.ToString());
534
Assert.AreEqual("System.Byte[]", d.Bytes.ToString());
535
Assert.AreEqual("http://json.codeplex.com/", d.Uri.ToString());
536
Assert.AreEqual("ea27fe1d-0d80-44f2-bf34-4654156fa7af", d.Guid.ToString());
537
Assert.AreEqual("1.00:00:00", d.TimeSpan.ToString());
541
public void JObjectGetDynamicPropertyNames()
543
JObject o = new JObject(
544
new JProperty("ChildValue", "blah blah"),
545
new JProperty("Hello Joe", null));
549
List<string> memberNames = o.GetDynamicMemberNames().ToList();
551
Assert.AreEqual(2, memberNames.Count);
552
Assert.AreEqual("ChildValue", memberNames[0]);
553
Assert.AreEqual("Hello Joe", memberNames[1]);
556
new JProperty("ChildValue1", "blah blah"),
557
new JProperty("Hello Joe1", null));
561
memberNames = o.GetDynamicMemberNames().ToList();
563
Assert.AreEqual(2, memberNames.Count);
564
Assert.AreEqual("ChildValue1", memberNames[0]);
565
Assert.AreEqual("Hello Joe1", memberNames[1]);
569
public void JValueConvert()
571
AssertValueConverted<bool>(true);
572
AssertValueConverted<bool?>(true);
573
AssertValueConverted<bool?>(false);
574
AssertValueConverted<bool?>(null);
575
AssertValueConverted<bool?>("true", true);
576
AssertValueConverted<byte[]>(null);
577
AssertValueConverted<byte[]>(Encoding.UTF8.GetBytes("blah"));
578
AssertValueConverted<DateTime>(new DateTime(2000, 12, 20, 23, 59, 2, DateTimeKind.Utc));
579
AssertValueConverted<DateTime?>(new DateTime(2000, 12, 20, 23, 59, 2, DateTimeKind.Utc));
580
AssertValueConverted<DateTime?>(null);
581
AssertValueConverted<DateTimeOffset>(new DateTimeOffset(2000, 12, 20, 23, 59, 2, TimeSpan.FromHours(1)));
582
AssertValueConverted<DateTimeOffset?>(new DateTimeOffset(2000, 12, 20, 23, 59, 2, TimeSpan.FromHours(1)));
583
AssertValueConverted<DateTimeOffset?>(null);
584
AssertValueConverted<decimal>(99.9m);
585
AssertValueConverted<decimal?>(99.9m);
586
AssertValueConverted<decimal>(1m);
587
AssertValueConverted<decimal>(1.1f, 1.1m);
588
AssertValueConverted<decimal>("1.1", 1.1m);
589
AssertValueConverted<double>(99.9);
590
AssertValueConverted<double>(99.9d);
591
AssertValueConverted<double?>(99.9d);
592
AssertValueConverted<float>(99.9f);
593
AssertValueConverted<float?>(99.9f);
594
AssertValueConverted<int>(int.MinValue);
595
AssertValueConverted<int?>(int.MinValue);
596
AssertValueConverted<long>(long.MaxValue);
597
AssertValueConverted<long?>(long.MaxValue);
598
AssertValueConverted<short>(short.MaxValue);
599
AssertValueConverted<short?>(short.MaxValue);
600
AssertValueConverted<string>("blah");
601
AssertValueConverted<string>(null);
602
AssertValueConverted<string>(1, "1");
603
AssertValueConverted<uint>(uint.MinValue);
604
AssertValueConverted<uint?>(uint.MinValue);
605
AssertValueConverted<uint?>("1", (uint)1);
606
AssertValueConverted<ulong>(ulong.MaxValue);
607
AssertValueConverted<ulong?>(ulong.MaxValue);
608
AssertValueConverted<ushort>(ushort.MinValue);
609
AssertValueConverted<ushort?>(ushort.MinValue);
610
AssertValueConverted<ushort?>(null);
611
AssertValueConverted<TimeSpan>(TimeSpan.FromDays(1));
612
AssertValueConverted<TimeSpan?>(TimeSpan.FromDays(1));
613
AssertValueConverted<TimeSpan?>(null);
614
AssertValueConverted<Guid>(new Guid("60304274-CD13-4060-B38C-057C8557AB54"));
615
AssertValueConverted<Guid?>(new Guid("60304274-CD13-4060-B38C-057C8557AB54"));
616
AssertValueConverted<Guid?>(null);
617
AssertValueConverted<Uri>(new Uri("http://json.codeplex.com/"));
618
AssertValueConverted<Uri>(null);
621
private static void AssertValueConverted<T>(object value)
623
AssertValueConverted<T>(value, value);
626
private static void AssertValueConverted<T>(object value, object expected)
628
JValue v = new JValue(value);
632
Assert.AreEqual(expected, t);
636
public void DynamicSerializerExample()
638
dynamic value = new DynamicDictionary();
640
value.Name = "Arine Admin";
641
value.Enabled = true;
642
value.Roles = new[] {"Admin", "User"};
644
string json = JsonConvert.SerializeObject(value, Formatting.Indented);
646
// "Name": "Arine Admin",
654
dynamic newValue = JsonConvert.DeserializeObject<DynamicDictionary>(json);
656
string role = newValue.Roles[0];
661
public void DynamicLinqExample()
663
JObject oldAndBusted = new JObject();
664
oldAndBusted["Name"] = "Arnie Admin";
665
oldAndBusted["Enabled"] = true;
666
oldAndBusted["Roles"] = new JArray(new[] { "Admin", "User" });
668
string oldRole = (string) oldAndBusted["Roles"][0];
672
dynamic newHotness = new JObject();
673
newHotness.Name = "Arnie Admin";
674
newHotness.Enabled = true;
675
newHotness.Roles = new JArray(new[] { "Admin", "User" });
677
string newRole = newHotness.Roles[0];
682
public void ImprovedDynamicLinqExample()
684
dynamic product = new JObject();
685
product.ProductName = "Elbow Grease";
686
product.Enabled = true;
687
product.Price = 4.90m;
688
product.StockCount = 9000;
689
product.StockValue = 44100;
691
// All Elbow Grease must go sale!
694
product.Price = product.Price / 2;
695
product.StockValue = product.StockCount * product.Price;
696
product.ProductName = product.ProductName + " (SALE)";
698
string json = product.ToString();
700
// "ProductName": "Elbow Grease (SALE)",
703
// "StockCount": 9000,
704
// "StockValue": 22050.00
708
""ProductName"": ""Elbow Grease (SALE)"",
711
""StockCount"": 9000,
712
""StockValue"": 22050.00
717
public class DynamicDictionary : DynamicObject
719
private readonly IDictionary<string, object> _values = new Dictionary<string, object>();
721
public override IEnumerable<string> GetDynamicMemberNames()
726
public override bool TryGetMember(GetMemberBinder binder, out object result)
728
result = _values[binder.Name];
732
public override bool TrySetMember(SetMemberBinder binder, object value)
734
_values[binder.Name] = value;
b'\\ No newline at end of file'