using System; using System.Collections.Generic; #if !NETFX_CORE using NUnit.Framework; #else using Microsoft.VisualStudio.TestTools.UnitTesting; using TestFixture = Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute; using Test = Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute; #endif using Newtonsoft.Json.Linq; #if NET20 using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; #endif namespace Newtonsoft.Json.Tests.Linq { [TestFixture] public class JPathTests : TestFixtureBase { [Test] public void SingleProperty() { JPath path = new JPath("Blah"); Assert.AreEqual(1, path.Parts.Count); Assert.AreEqual("Blah", path.Parts[0]); } [Test] public void TwoProperties() { JPath path = new JPath("Blah.Two"); Assert.AreEqual(2, path.Parts.Count); Assert.AreEqual("Blah", path.Parts[0]); Assert.AreEqual("Two", path.Parts[1]); } [Test] public void SinglePropertyAndIndexer() { JPath path = new JPath("Blah[0]"); Assert.AreEqual(2, path.Parts.Count); Assert.AreEqual("Blah", path.Parts[0]); Assert.AreEqual(0, path.Parts[1]); } [Test] public void MultiplePropertiesAndIndexers() { JPath path = new JPath("Blah[0].Two.Three[1].Four"); Assert.AreEqual(6, path.Parts.Count); Assert.AreEqual("Blah", path.Parts[0]); Assert.AreEqual(0, path.Parts[1]); Assert.AreEqual("Two", path.Parts[2]); Assert.AreEqual("Three", path.Parts[3]); Assert.AreEqual(1, path.Parts[4]); Assert.AreEqual("Four", path.Parts[5]); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = @"Unexpected character while parsing path indexer: [" #endif )] public void BadCharactersInIndexer() { new JPath("Blah[[0]].Two.Three[1].Four"); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = @"Path ended with open indexer. Expected ]" #endif )] public void UnclosedIndexer() { new JPath("Blah[0"); } [Test] public void AdditionalDots() { JPath path = new JPath(".Blah..[0]..Two.Three....[1].Four."); Assert.AreEqual(6, path.Parts.Count); Assert.AreEqual("Blah", path.Parts[0]); Assert.AreEqual(0, path.Parts[1]); Assert.AreEqual("Two", path.Parts[2]); Assert.AreEqual("Three", path.Parts[3]); Assert.AreEqual(1, path.Parts[4]); Assert.AreEqual("Four", path.Parts[5]); } [Test] public void IndexerOnly() { JPath path = new JPath("[111119990]"); Assert.AreEqual(1, path.Parts.Count); Assert.AreEqual(111119990, path.Parts[0]); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = "Empty path indexer." #endif )] public void EmptyIndexer() { new JPath("[]"); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = "Unexpected character while parsing path: ]" #endif )] public void IndexerCloseInProperty() { new JPath("]"); } [Test] public void AdjacentIndexers() { JPath path = new JPath("[1][0][0][" + int.MaxValue + "]"); Assert.AreEqual(4, path.Parts.Count); Assert.AreEqual(1, path.Parts[0]); Assert.AreEqual(0, path.Parts[1]); Assert.AreEqual(0, path.Parts[2]); Assert.AreEqual(int.MaxValue, path.Parts[3]); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = "Unexpected character following indexer: B" #endif )] public void MissingDotAfterIndexer() { new JPath("[1]Blah"); } [Test] public void EvaluateSingleProperty() { JObject o = new JObject( new JProperty("Blah", 1)); JToken t = o.SelectToken("Blah"); Assert.IsNotNull(t); Assert.AreEqual(JTokenType.Integer, t.Type); Assert.AreEqual(1, (int)t); } [Test] public void EvaluateMissingProperty() { JObject o = new JObject( new JProperty("Blah", 1)); JToken t = o.SelectToken("Missing[1]"); Assert.IsNull(t); } [Test] public void EvaluateIndexerOnObject() { JObject o = new JObject( new JProperty("Blah", 1)); JToken t = o.SelectToken("[1]"); Assert.IsNull(t); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = @"Index 1 not valid on JObject." #endif )] public void EvaluateIndexerOnObjectWithError() { JObject o = new JObject( new JProperty("Blah", 1)); o.SelectToken("[1]", true); } [Test] public void EvaluatePropertyOnArray() { JArray a = new JArray(1, 2, 3, 4, 5); JToken t = a.SelectToken("BlahBlah"); Assert.IsNull(t); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = @"Property 'BlahBlah' not valid on JArray." #endif )] public void EvaluatePropertyOnArrayWithError() { JArray a = new JArray(1, 2, 3, 4, 5); a.SelectToken("BlahBlah", true); } [Test] [ExpectedException(typeof(IndexOutOfRangeException) #if !NETFX_CORE , ExpectedMessage = @"Index 1 outside the bounds of JConstructor." #endif )] public void EvaluateConstructorOutOfBoundsIndxerWithError() { JConstructor c = new JConstructor("Blah"); c.SelectToken("[1]", true); } [Test] [ExpectedException(typeof(Exception) #if !NETFX_CORE , ExpectedMessage = "Property 'Missing' does not exist on JObject." #endif )] public void EvaluateMissingPropertyWithError() { JObject o = new JObject( new JProperty("Blah", 1)); o.SelectToken("Missing", true); } [Test] public void EvaluateOutOfBoundsIndxer() { JArray a = new JArray(1, 2, 3, 4, 5); JToken t = a.SelectToken("[1000].Ha"); Assert.IsNull(t); } [Test] [ExpectedException(typeof(IndexOutOfRangeException) #if !NETFX_CORE , ExpectedMessage = "Index 1000 outside the bounds of JArray." #endif )] public void EvaluateArrayOutOfBoundsIndxerWithError() { JArray a = new JArray(1, 2, 3, 4, 5); a.SelectToken("[1000].Ha", true); } [Test] public void EvaluateArray() { JArray a = new JArray(1, 2, 3, 4); JToken t = a.SelectToken("[1]"); Assert.IsNotNull(t); Assert.AreEqual(JTokenType.Integer, t.Type); Assert.AreEqual(2, (int)t); } [Test] public void EvaluateSinglePropertyReturningArray() { JObject o = new JObject( new JProperty("Blah", new [] { 1, 2, 3 })); JToken t = o.SelectToken("Blah"); Assert.IsNotNull(t); Assert.AreEqual(JTokenType.Array, t.Type); t = o.SelectToken("Blah[2]"); Assert.AreEqual(JTokenType.Integer, t.Type); Assert.AreEqual(3, (int)t); } [Test] public void EvaluateLastSingleCharacterProperty() { JObject o2 = JObject.Parse("{'People':[{'N':'Jeff'}]}"); string a2 = (string)o2.SelectToken("People[0].N"); Assert.AreEqual("Jeff", a2); } [Test] public void PathWithConstructor() { JArray a = JArray.Parse(@"[ { ""Property1"": [ 1, [ [ [] ] ] ] }, { ""Property2"": new Constructor1( null, [ 1 ] ) } ]"); JValue v = (JValue)a.SelectToken("[1].Property2[1][0]"); Assert.AreEqual(1L, v.Value); } [Test] public void Example() { JObject o = JObject.Parse(@"{ ""Stores"": [ ""Lambton Quay"", ""Willis Street"" ], ""Manufacturers"": [ { ""Name"": ""Acme Co"", ""Products"": [ { ""Name"": ""Anvil"", ""Price"": 50 } ] }, { ""Name"": ""Contoso"", ""Products"": [ { ""Name"": ""Elbow Grease"", ""Price"": 99.95 }, { ""Name"": ""Headlight Fluid"", ""Price"": 4 } ] } ] }"); string name = (string)o.SelectToken("Manufacturers[0].Name"); // Acme Co decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price"); // 50 string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name"); // Elbow Grease Assert.AreEqual("Acme Co", name); Assert.AreEqual(50m, productPrice); Assert.AreEqual("Elbow Grease", productName); IList storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList(); // Lambton Quay // Willis Street IList firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList(); // null // Headlight Fluid decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price")); // 149.95 Assert.AreEqual(2, storeNames.Count); Assert.AreEqual("Lambton Quay", storeNames[0]); Assert.AreEqual("Willis Street", storeNames[1]); Assert.AreEqual(2, firstProductNames.Count); Assert.AreEqual(null, firstProductNames[0]); Assert.AreEqual("Headlight Fluid", firstProductNames[1]); Assert.AreEqual(149.95m, totalPrice); } } }