-Fixed incorrectly parsing scan filter when name is quoted

-Added support for multiple names in scan filter
This commit is contained in:
James Newton-King
2016-10-28 13:25:52 +13:00
parent 26d8871254
commit ae074a3469
9 changed files with 152 additions and 12 deletions
@@ -51,6 +51,81 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
[TestFixture]
public class JPathExecuteTests : TestFixtureBase
{
[Test]
public void ScanQuoted()
{
string json = @"{
""Node1"": {
""Child1"": {
""Name"": ""IsMe"",
""TargetNode"": {
""Prop1"": ""Val1"",
""Prop2"": ""Val2""
}
},
""My.Child.Node"": {
""TargetNode"": {
""Prop1"": ""Val1"",
""Prop2"": ""Val2""
}
}
},
""Node2"": {
""TargetNode"": {
""Prop1"": ""Val1"",
""Prop2"": ""Val2""
}
}
}";
JObject models = JObject.Parse(json);
int result = models.SelectTokens("$..['My.Child.Node']").Count();
Assert.AreEqual(1, result);
result = models.SelectTokens("..['My.Child.Node']").Count();
Assert.AreEqual(1, result);
}
[Test]
public void ScanMultipleQuoted()
{
string json = @"{
""Node1"": {
""Child1"": {
""Name"": ""IsMe"",
""TargetNode"": {
""Prop1"": ""Val1"",
""Prop2"": ""Val2""
}
},
""My.Child.Node"": {
""TargetNode"": {
""Prop1"": ""Val3"",
""Prop2"": ""Val4""
}
}
},
""Node2"": {
""TargetNode"": {
""Prop1"": ""Val5"",
""Prop2"": ""Val6""
}
}
}";
JObject models = JObject.Parse(json);
var results = models.SelectTokens("$..['My.Child.Node','Prop1','Prop2']").ToList();
Assert.AreEqual("Val1", (string)results[0]);
Assert.AreEqual("Val2", (string)results[1]);
Assert.AreEqual(JTokenType.Object, results[2].Type);
Assert.AreEqual("Val3", (string)results[3]);
Assert.AreEqual("Val4", (string)results[4]);
Assert.AreEqual("Val5", (string)results[5]);
Assert.AreEqual("Val6", (string)results[6]);
}
[Test]
public void ParseWithEmptyArrayContent()
{
+17 -12
View File
@@ -111,12 +111,11 @@ namespace Newtonsoft.Json.Linq.JsonPath
member = null;
}
PathFilter filter = (scan) ? (PathFilter)new ScanFilter { Name = member } : new FieldFilter { Name = member };
filters.Add(filter);
filters.Add(CreatePathFilter(member, scan));
scan = false;
}
filters.Add(ParseIndexer(currentChar));
filters.Add(ParseIndexer(currentChar, scan));
_currentIndex++;
currentPartStartIndex = _currentIndex;
followingIndexer = true;
@@ -141,8 +140,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
member = null;
}
PathFilter filter = (scan) ? (PathFilter)new ScanFilter { Name = member } : new FieldFilter { Name = member };
filters.Add(filter);
filters.Add(CreatePathFilter(member, scan));
scan = false;
}
if (_currentIndex + 1 < _expression.Length && _expression[_currentIndex + 1] == '.')
@@ -182,8 +180,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
{
member = null;
}
PathFilter filter = (scan) ? (PathFilter)new ScanFilter { Name = member } : new FieldFilter { Name = member };
filters.Add(filter);
filters.Add(CreatePathFilter(member, scan));
}
else
{
@@ -197,7 +194,13 @@ namespace Newtonsoft.Json.Linq.JsonPath
return atPathEnd;
}
private PathFilter ParseIndexer(char indexerOpenChar)
private static PathFilter CreatePathFilter(string member, bool scan)
{
PathFilter filter = (scan) ? (PathFilter)new ScanFilter {Name = member} : new FieldFilter {Name = member};
return filter;
}
private PathFilter ParseIndexer(char indexerOpenChar, bool scan)
{
_currentIndex++;
@@ -209,7 +212,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
if (_expression[_currentIndex] == '\'')
{
return ParseQuotedField(indexerCloseChar);
return ParseQuotedField(indexerCloseChar, scan);
}
else if (_expression[_currentIndex] == '?')
{
@@ -710,7 +713,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
throw new JsonException("Could not read query operator.");
}
private PathFilter ParseQuotedField(char indexerCloseChar)
private PathFilter ParseQuotedField(char indexerCloseChar, bool scan)
{
List<string> fields = null;
@@ -726,11 +729,13 @@ namespace Newtonsoft.Json.Linq.JsonPath
if (fields != null)
{
fields.Add(field);
return new FieldMultipleFilter { Names = fields };
return (scan)
? (PathFilter)new ScanMultipleFilter { Names = fields }
: (PathFilter)new FieldMultipleFilter { Names = fields };
}
else
{
return new FieldFilter { Name = field };
return CreatePathFilter(field, scan);
}
}
else if (_expression[_currentIndex] == ',')
@@ -0,0 +1,54 @@
using System.Collections.Generic;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class ScanMultipleFilter : PathFilter
{
public List<string> Names { get; set; }
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken c in current)
{
JToken value = c;
JToken container = c;
while (true)
{
if (container != null && container.HasValues)
{
value = container.First;
}
else
{
while (value != null && value != c && value == value.Parent.Last)
{
value = value.Parent;
}
if (value == null || value == c)
{
break;
}
value = value.Next;
}
JProperty e = value as JProperty;
if (e != null)
{
foreach (string name in Names)
{
if (e.Name == name)
{
yield return e.Value;
}
}
}
container = value as JContainer;
}
}
}
}
}
@@ -125,6 +125,7 @@
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
<Compile Include="Linq\JsonPath\RootFilter.cs" />
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
<Compile Include="Linq\JsonPath\ScanMultipleFilter.cs" />
<Compile Include="Linq\MergeArrayHandling.cs" />
<Compile Include="Linq\MergeNullValueHandling.cs" />
<Compile Include="MetadataPropertyHandling.cs" />
@@ -139,6 +139,7 @@
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
<Compile Include="Linq\JsonPath\RootFilter.cs" />
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
<Compile Include="Linq\JsonPath\ScanMultipleFilter.cs" />
<Compile Include="Linq\MergeArrayHandling.cs" />
<Compile Include="Linq\MergeNullValueHandling.cs" />
<Compile Include="MetadataPropertyHandling.cs" />
@@ -140,6 +140,7 @@
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
<Compile Include="Linq\JsonPath\RootFilter.cs" />
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
<Compile Include="Linq\JsonPath\ScanMultipleFilter.cs" />
<Compile Include="Linq\MergeArrayHandling.cs" />
<Compile Include="Linq\MergeNullValueHandling.cs" />
<Compile Include="MetadataPropertyHandling.cs" />
@@ -130,6 +130,7 @@
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
<Compile Include="Linq\JsonPath\RootFilter.cs" />
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
<Compile Include="Linq\JsonPath\ScanMultipleFilter.cs" />
<Compile Include="Linq\JToken.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />
<Compile Include="Linq\JTokenReader.cs" />
@@ -135,6 +135,7 @@
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
<Compile Include="Linq\JsonPath\RootFilter.cs" />
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
<Compile Include="Linq\JsonPath\ScanMultipleFilter.cs" />
<Compile Include="Linq\JToken.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />
<Compile Include="Linq\JTokenReader.cs" />
@@ -131,6 +131,7 @@
<Compile Include="Linq\JsonPath\QueryExpression.cs" />
<Compile Include="Linq\JsonPath\QueryFilter.cs" />
<Compile Include="Linq\JsonPath\RootFilter.cs" />
<Compile Include="Linq\JsonPath\ScanMultipleFilter.cs" />
<Compile Include="Linq\JsonPath\ScanFilter.cs" />
<Compile Include="Linq\JToken.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />