context: #region License
  // Copyright (c) 2007 James Newton-King
  //
  // Permission is hereby granted, free of charge, to any person
  // obtaining a copy of this software and associated documentation
  // files (the "Software"), to deal in the Software without
  // restriction, including without limitation the rights to use,
  // copy, modify, merge, publish, distribute, sublicense, and/or sell
  // copies of the Software, and to permit persons to whom the
  // Software is furnished to do so, subject to the following
  // conditions:
  //
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  // OTHER DEALINGS IN THE SOFTWARE.
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Collections.Specialized;
  using System.ComponentModel;
  using Newtonsoft.Json.Tests.TestObjects;
  #if !NETFX_CORE
  using NUnit.Framework;
  #else
  using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
  using TestFixture = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute;
  using Test = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute;
  #endif
  using Newtonsoft.Json.Linq;
  using System.IO;
  using System.Collections;
  #if !PocketPC && !SILVERLIGHT && !NETFX_CORE
  using System.Web.UI;
  #endif
  #if NET20
  using Newtonsoft.Json.Utilities.LinqBridge;
  #else
  using System.Linq;
  #endif
  
  namespace Newtonsoft.Json.Tests.Linq
  {
    [TestFixture]
    public class JObjectTests : TestFixtureBase
    {
      [Test]
      public void WritePropertyWithNoValue()
      {
        var o = new JObject();
        o.Add(new JProperty("novalue"));
  
        Assert.AreEqual(@"{
    ""novalue"": null
  }", o.ToString());
      }
  
      [Test]
      public void Keys()
      {
        var o = new JObject();
        var d = (IDictionary<string, JToken>) o;
  
        Assert.AreEqual(0, d.Keys.Count);
  
        o["value"] = true;
  
        Assert.AreEqual(1, d.Keys.Count);
      }
  
      [Test]
      public void TryGetValue()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue", new JValue(1));
        Assert.AreEqual(1, o.Children().Count());
  
        JToken t;
        Assert.AreEqual(false, o.TryGetValue("sdf", out t));
        Assert.AreEqual(null, t);
  
        Assert.AreEqual(false, o.TryGetValue(null, out t));
        Assert.AreEqual(null, t);
  
        Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
        Assert.AreEqual(true, JToken.DeepEquals(new JValue(1), t));
      }
  
      [Test]
      public void DictionaryItemShouldSet()
      {
        JObject o = new JObject();
        o["PropertyNameValue"] = new JValue(1);
        Assert.AreEqual(1, o.Children().Count());
  
        JToken t;
        Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
        Assert.AreEqual(true, JToken.DeepEquals(new JValue(1), t));
  
        o["PropertyNameValue"] = new JValue(2);
        Assert.AreEqual(1, o.Children().Count());
  
        Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
        Assert.AreEqual(true, JToken.DeepEquals(new JValue(2), t));
  
        o["PropertyNameValue"] = null;
        Assert.AreEqual(1, o.Children().Count());
  
        Assert.AreEqual(true, o.TryGetValue("PropertyNameValue", out t));
        Assert.AreEqual(true, JToken.DeepEquals(new JValue((object)null), t));
      }
  
      [Test]
      public void Remove()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue", new JValue(1));
        Assert.AreEqual(1, o.Children().Count());
  
        Assert.AreEqual(false, o.Remove("sdf"));
        Assert.AreEqual(false, o.Remove(null));
        Assert.AreEqual(true, o.Remove("PropertyNameValue"));
  
        Assert.AreEqual(0, o.Children().Count());
      }
  
      [Test]
      public void GenericCollectionRemove()
      {
        JValue v = new JValue(1);
        JObject o = new JObject();
        o.Add("PropertyNameValue", v);
        Assert.AreEqual(1, o.Children().Count());
  
        Assert.AreEqual(false, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue1", new JValue(1))));
        Assert.AreEqual(false, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(2))));
        Assert.AreEqual(false, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(1))));
        Assert.AreEqual(true, ((ICollection<KeyValuePair<string, JToken>>)o).Remove(new KeyValuePair<string, JToken>("PropertyNameValue", v)));
  
        Assert.AreEqual(0, o.Children().Count());
      }
  
      [Test]
      public void DuplicatePropertyNameShouldThrow()
      {
        ExceptionAssert.Throws<ArgumentException>(
          "Can not add property PropertyNameValue to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.",
          () =>
          {
            JObject o = new JObject();
            o.Add("PropertyNameValue", null);
            o.Add("PropertyNameValue", null);
          });
      }
  
      [Test]
      public void GenericDictionaryAdd()
      {
        JObject o = new JObject();
  
        o.Add("PropertyNameValue", new JValue(1));
        Assert.AreEqual(1, (int)o["PropertyNameValue"]);
  
        o.Add("PropertyNameValue1", null);
        Assert.AreEqual(null, ((JValue)o["PropertyNameValue1"]).Value);
  
        Assert.AreEqual(2, o.Children().Count());
      }
  
      [Test]
      public void GenericCollectionAdd()
      {
        JObject o = new JObject();
        ((ICollection<KeyValuePair<string,JToken>>)o).Add(new KeyValuePair<string,JToken>("PropertyNameValue", new JValue(1)));
  
        Assert.AreEqual(1, (int)o["PropertyNameValue"]);
        Assert.AreEqual(1, o.Children().Count());
      }
  
      [Test]
      public void GenericCollectionClear()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue", new JValue(1));
        Assert.AreEqual(1, o.Children().Count());
  
        JProperty p = (JProperty)o.Children().ElementAt(0);
  
        ((ICollection<KeyValuePair<string, JToken>>)o).Clear();
        Assert.AreEqual(0, o.Children().Count());
  
        Assert.AreEqual(null, p.Parent);
      }
  
      [Test]
      public void GenericCollectionContains()
      {
        JValue v = new JValue(1);
        JObject o = new JObject();
        o.Add("PropertyNameValue", v);
        Assert.AreEqual(1, o.Children().Count());
  
        bool contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(1)));
        Assert.AreEqual(false, contains);
  
        contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue", v));
        Assert.AreEqual(true, contains);
  
        contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue", new JValue(2)));
        Assert.AreEqual(false, contains);
  
        contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(new KeyValuePair<string, JToken>("PropertyNameValue1", new JValue(1)));
        Assert.AreEqual(false, contains);
  
        contains = ((ICollection<KeyValuePair<string, JToken>>)o).Contains(default(KeyValuePair<string, JToken>));
        Assert.AreEqual(false, contains);
      }
  
      [Test]
      public void GenericDictionaryContains()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue", new JValue(1));
        Assert.AreEqual(1, o.Children().Count());
  
        bool contains = ((IDictionary<string, JToken>)o).ContainsKey("PropertyNameValue");
        Assert.AreEqual(true, contains);
      }
  
      [Test]
      public void GenericCollectionCopyTo()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue", new JValue(1));
        o.Add("PropertyNameValue2", new JValue(2));
        o.Add("PropertyNameValue3", new JValue(3));
        Assert.AreEqual(3, o.Children().Count());
  
        KeyValuePair<string, JToken>[] a = new KeyValuePair<string,JToken>[5];
  
        ((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(a, 1);
  
        Assert.AreEqual(default(KeyValuePair<string,JToken>), a[0]);
        
        Assert.AreEqual("PropertyNameValue", a[1].Key);
        Assert.AreEqual(1, (int)a[1].Value);
  
        Assert.AreEqual("PropertyNameValue2", a[2].Key);
        Assert.AreEqual(2, (int)a[2].Value);
  
        Assert.AreEqual("PropertyNameValue3", a[3].Key);
        Assert.AreEqual(3, (int)a[3].Value);
  
        Assert.AreEqual(default(KeyValuePair<string, JToken>), a[4]);
      }
  
      [Test]
      public void GenericCollectionCopyToNullArrayShouldThrow()
      {
        ExceptionAssert.Throws<ArgumentException>(
          @"Value cannot be null.
  Parameter name: array",
          () =>
          {
            JObject o = new JObject();
            ((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(null, 0);
          });
      }
  
      [Test]
      public void GenericCollectionCopyToNegativeArrayIndexShouldThrow()
      {
        ExceptionAssert.Throws<ArgumentOutOfRangeException>(
          @"arrayIndex is less than 0.
  Parameter name: arrayIndex",
          () =>
          {
            JObject o = new JObject();
            ((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(new KeyValuePair<string, JToken>[1], -1);
          });
      }
  
      [Test]
      public void GenericCollectionCopyToArrayIndexEqualGreaterToArrayLengthShouldThrow()
      {
        ExceptionAssert.Throws<ArgumentException>(
          @"arrayIndex is equal to or greater than the length of array.",
          () =>
          {
            JObject o = new JObject();
            ((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(new KeyValuePair<string, JToken>[1], 1);
          });
      }
  
      [Test]
      public void GenericCollectionCopyToInsufficientArrayCapacity()
      {
        ExceptionAssert.Throws<ArgumentException>(
          @"The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.",
          () =>
          {
            JObject o = new JObject();
            o.Add("PropertyNameValue", new JValue(1));
            o.Add("PropertyNameValue2", new JValue(2));
            o.Add("PropertyNameValue3", new JValue(3));
  
            ((ICollection<KeyValuePair<string, JToken>>)o).CopyTo(new KeyValuePair<string, JToken>[3], 1);
          });
      }
  
      [Test]
      public void FromObjectRaw()
      {
        PersonRaw raw = new PersonRaw
        {
          FirstName = "FirstNameValue",
          RawContent = new JRaw("[1,2,3,4,5]"),
          LastName = "LastNameValue"
        };
  
        JObject o = JObject.FromObject(raw);
  
        Assert.AreEqual("FirstNameValue", (string)o["first_name"]);
        Assert.AreEqual(JTokenType.Raw, ((JValue)o["RawContent"]).Type);
        Assert.AreEqual("[1,2,3,4,5]", (string)o["RawContent"]);
        Assert.AreEqual("LastNameValue", (string)o["last_name"]);
      }
  
      [Test]
      public void JTokenReader()
      {
        PersonRaw raw = new PersonRaw
        {
          FirstName = "FirstNameValue",
          RawContent = new JRaw("[1,2,3,4,5]"),
          LastName = "LastNameValue"
        };
  
        JObject o = JObject.FromObject(raw);
  
        JsonReader reader = new JTokenReader(o);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.String, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.Raw, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.String, reader.TokenType);
  
        Assert.IsTrue(reader.Read());
        Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
  
        Assert.IsFalse(reader.Read());
      }
  
      [Test]
      public void DeserializeFromRaw()
      {
        PersonRaw raw = new PersonRaw
        {
          FirstName = "FirstNameValue",
          RawContent = new JRaw("[1,2,3,4,5]"),
          LastName = "LastNameValue"
        };
  
        JObject o = JObject.FromObject(raw);
  
        JsonReader reader = new JTokenReader(o);
        JsonSerializer serializer = new JsonSerializer();
        raw = (PersonRaw)serializer.Deserialize(reader, typeof(PersonRaw));
  
        Assert.AreEqual("FirstNameValue", raw.FirstName);
        Assert.AreEqual("LastNameValue", raw.LastName);
        Assert.AreEqual("[1,2,3,4,5]", raw.RawContent.Value);
      }
  
      [Test]
      public void Parse_ShouldThrowOnUnexpectedToken()
      {
        ExceptionAssert.Throws<JsonReaderException>("Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.",
          () =>
          {
            string json = @"[""prop""]";
            JObject.Parse(json);
          });
      }
  
      [Test]
      public void ParseJavaScriptDate()
      {
        string json = @"[new Date(1207285200000)]";
  
        JArray a = (JArray)JsonConvert.DeserializeObject(json);
        JValue v = (JValue)a[0];
  
        Assert.AreEqual(JsonConvert.ConvertJavaScriptTicksToDateTime(1207285200000), (DateTime)v);
      }
  
      [Test]
      public void GenericValueCast()
      {
        string json = @"{""foo"":true}";
        JObject o = (JObject)JsonConvert.DeserializeObject(json);
        bool? value = o.Value<bool?>("foo");
        Assert.AreEqual(true, value);
  
        json = @"{""foo"":null}"; 
        o = (JObject)JsonConvert.DeserializeObject(json);
        value = o.Value<bool?>("foo");
        Assert.AreEqual(null, value);
      }
  
      [Test]
      public void Blog()
      {
        ExceptionAssert.Throws<JsonReaderException>(
          "Invalid property identifier character: ]. Path 'name', line 3, position 5.",
          () =>
          {
            JObject.Parse(@"{
      ""name"": ""James"",
      ]!#$THIS IS: BAD JSON![{}}}}]
    }");
          });
      }
  
      [Test]
      public void RawChildValues()
      {
        JObject o = new JObject();
        o["val1"] = new JRaw("1");
        o["val2"] = new JRaw("1");
  
        string json = o.ToString();
  
        Assert.AreEqual(@"{
    ""val1"": 1,
    ""val2"": 1
  }", json);
      }
  
      [Test]
      public void Iterate()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue1", new JValue(1));
        o.Add("PropertyNameValue2", new JValue(2));
  
        JToken t = o;
  
        int i = 1;
        foreach (JProperty property in t)
        {
          Assert.AreEqual("PropertyNameValue" + i, property.Name);
          Assert.AreEqual(i, (int)property.Value);
  
          i++;
        }
      }
  
      [Test]
      public void KeyValuePairIterate()
      {
        JObject o = new JObject();
        o.Add("PropertyNameValue1", new JValue(1));
        o.Add("PropertyNameValue2", new JValue(2));
  
        int i = 1;
        foreach (KeyValuePair<string, JToken> pair in o)
        {
          Assert.AreEqual("PropertyNameValue" + i, pair.Key);
          Assert.AreEqual(i, (int)pair.Value);
  
          i++;
        }
      }
  
      [Test]
      public void WriteObjectNullStringValue()
      {
        string s = null;
        JValue v = new JValue(s);
        Assert.AreEqual(null, v.Value);
        Assert.AreEqual(JTokenType.String, v.Type);
  
        JObject o = new JObject();
        o["title"] = v;
  
        string output = o.ToString();
        
        Assert.AreEqual(@"{
    ""title"": null
  }", output);
      }
  
      [Test]
      public void Example()
      {
        string json = @"{
          ""Name"": ""Apple"",
          ""Expiry"": new Date(1230422400000),
          ""Price"": 3.99,
          ""Sizes"": [
            ""Small"",
            ""Medium"",
            ""Large""
          ]
        }";
  
        JObject o = JObject.Parse(json);
  
        string name = (string)o["Name"];
        // Apple
  
        JArray sizes = (JArray)o["Sizes"];
  
        string smallest = (string)sizes[0];
        // Small
  
        Console.WriteLine(name);
        Console.WriteLine(smallest);
      }
  
      [Test]
      public void DeserializeClassManually()
      {
        string jsonText = @"{
    ""short"":
    {
      ""original"":""http://www.foo.com/"",
      ""short"":""krehqk"",
      ""error"":
      {
        ""code"":0,
        ""msg"":""No action taken""
      }
    }
  }";
  
        JObject json = JObject.Parse(jsonText);
  
        Shortie shortie = new Shortie
                          {
                            Original = (string)json["short"]["original"],
                            Short = (string)json["short"]["short"],
                            Error = new ShortieException
                                    {
                                      Code = (int)json["short"]["error"]["code"],
                                      ErrorMessage = (string)json["short"]["error"]["msg"]
                                    }
                          };
  
        Console.WriteLine(shortie.Original);
        // http://www.foo.com/
  
        Console.WriteLine(shortie.Error.ErrorMessage);
        // No action taken
  
        Assert.AreEqual("http://www.foo.com/", shortie.Original);
        Assert.AreEqual("krehqk", shortie.Short);
        Assert.AreEqual(null, shortie.Shortened);
        Assert.AreEqual(0, shortie.Error.Code);
        Assert.AreEqual("No action taken", shortie.Error.ErrorMessage);
      }
  
      [Test]
      public void JObjectContainingHtml()
      {
        JObject o = new JObject();
        o["rc"] = new JValue(200);
        o["m"] = new JValue("");
        o["o"] = new JValue(@"<div class='s1'>
      <div class='avatar'>                    
          <a href='asdf'>asdf</a><br />
          <strong>0</strong>
      </div>
      <div class='sl'>
          <p>
              444444444
          </p>
      </div>
      <div class='clear'>
      </div>                        
  </div>");
  
        Assert.AreEqual(@"{
    ""rc"": 200,
    ""m"": """",
    ""o"": ""<div class='s1'>\r\n    <div class='avatar'>                    \r\n        <a href='asdf'>asdf</a><br />\r\n        <strong>0</strong>\r\n    </div>\r\n    <div class='sl'>\r\n        <p>\r\n            444444444\r\n        </p>\r\n    </div>\r\n    <div class='clear'>\r\n    </div>                        \r\n</div>""
  }", o.ToString());
      }
  
      [Test]
      public void ImplicitValueConversions()
      {
        JObject moss = new JObject();
        moss["FirstName"] = new JValue("Maurice");
        moss["LastName"] = new JValue("Moss");
        moss["BirthDate"] = new JValue(new DateTime(1977, 12, 30));
        moss["Department"] = new JValue("IT");
        moss["JobTitle"] = new JValue("Support");
  
        Console.WriteLine(moss.ToString());
        //{
        //  "FirstName": "Maurice",
        //  "LastName": "Moss",
        //  "BirthDate": "\/Date(252241200000+1300)\/",
        //  "Department": "IT",
        //  "JobTitle": "Support"
        //}
  
  
        JObject jen = new JObject();
        jen["FirstName"] = "Jen";
        jen["LastName"] = "Barber";
  
gt:       jen["BirthDate"] = new DateTime(1978, 3, 15);