-Refactor regex in JSON Path
This commit is contained in:
@@ -315,16 +315,44 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SinglePropertyAndFilterWithRegex()
|
||||
public void SinglePropertyAndFilterWithRegexAndOptions()
|
||||
{
|
||||
JPath path = new JPath("Blah[ ?( @.name=~/hi/i ) ]");
|
||||
Assert.AreEqual(2, path.Filters.Count);
|
||||
Assert.AreEqual("Blah", ((FieldFilter)path.Filters[0]).Name);
|
||||
BooleanQueryExpression expressions = (BooleanQueryExpression)((QueryFilter)path.Filters[1]).Expression;
|
||||
Assert.AreEqual(QueryOperator.RegExEquals, expressions.Operator);
|
||||
Assert.AreEqual(QueryOperator.RegexEquals, expressions.Operator);
|
||||
Assert.AreEqual("/hi/i", (string)(JToken)expressions.Right);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SinglePropertyAndFilterWithRegex()
|
||||
{
|
||||
JPath path = new JPath("Blah[?(@.title =~ /^.*Sword.*$/)]");
|
||||
Assert.AreEqual(2, path.Filters.Count);
|
||||
Assert.AreEqual("Blah", ((FieldFilter)path.Filters[0]).Name);
|
||||
BooleanQueryExpression expressions = (BooleanQueryExpression)((QueryFilter)path.Filters[1]).Expression;
|
||||
Assert.AreEqual(QueryOperator.RegexEquals, expressions.Operator);
|
||||
Assert.AreEqual("/^.*Sword.*$/", (string)(JToken)expressions.Right);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SinglePropertyAndFilterWithEscapedRegex()
|
||||
{
|
||||
JPath path = new JPath(@"Blah[?(@.title =~ /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g)]");
|
||||
Assert.AreEqual(2, path.Filters.Count);
|
||||
Assert.AreEqual("Blah", ((FieldFilter)path.Filters[0]).Name);
|
||||
BooleanQueryExpression expressions = (BooleanQueryExpression)((QueryFilter)path.Filters[1]).Expression;
|
||||
Assert.AreEqual(QueryOperator.RegexEquals, expressions.Operator);
|
||||
Assert.AreEqual(@"/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g", (string)(JToken)expressions.Right);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SinglePropertyAndFilterWithOpenRegex()
|
||||
{
|
||||
ExceptionAssert.Throws<JsonException>(() => { new JPath(@"Blah[?(@.title =~ /[\"); }, "Path ended with an open regex.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SinglePropertyAndFilterWithUnknownEscape()
|
||||
{
|
||||
|
||||
@@ -159,11 +159,11 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BooleanExpressionTest_RegExEqualsOperator()
|
||||
public void BooleanExpressionTest_RegexEqualsOperator()
|
||||
{
|
||||
BooleanQueryExpression e1 = new BooleanQueryExpression
|
||||
{
|
||||
Operator = QueryOperator.RegExEquals,
|
||||
Operator = QueryOperator.RegexEquals,
|
||||
Right = new JValue("/foo.*d/"),
|
||||
Left = new List<PathFilter>
|
||||
{
|
||||
@@ -178,7 +178,7 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
|
||||
|
||||
BooleanQueryExpression e2 = new BooleanQueryExpression
|
||||
{
|
||||
Operator = QueryOperator.RegExEquals,
|
||||
Operator = QueryOperator.RegexEquals,
|
||||
Right = new JValue("/Foo.*d/i"),
|
||||
Left = new List<PathFilter>
|
||||
{
|
||||
@@ -193,11 +193,11 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BooleanExpressionTest_RegExEqualsOperator_CornerCase()
|
||||
public void BooleanExpressionTest_RegexEqualsOperator_CornerCase()
|
||||
{
|
||||
BooleanQueryExpression e1 = new BooleanQueryExpression
|
||||
{
|
||||
Operator = QueryOperator.RegExEquals,
|
||||
Operator = QueryOperator.RegexEquals,
|
||||
Right = new JValue("/// comment/"),
|
||||
Left = new List<PathFilter>
|
||||
{
|
||||
@@ -210,7 +210,7 @@ namespace Newtonsoft.Json.Tests.Linq.JsonPath
|
||||
|
||||
BooleanQueryExpression e2 = new BooleanQueryExpression
|
||||
{
|
||||
Operator = QueryOperator.RegExEquals,
|
||||
Operator = QueryOperator.RegexEquals,
|
||||
Right = new JValue("/<tag>.*</tag>/i"),
|
||||
Left = new List<PathFilter>
|
||||
{
|
||||
|
||||
@@ -719,79 +719,45 @@ namespace Newtonsoft.Json.Linq.JsonPath
|
||||
|
||||
private string ReadRegexString()
|
||||
{
|
||||
var sb = new StringBuilder("/");
|
||||
int startIndex = _currentIndex;
|
||||
|
||||
_currentIndex++;
|
||||
while (_currentIndex < _expression.Length)
|
||||
{
|
||||
char currentChar = _expression[_currentIndex];
|
||||
|
||||
// handle escaped / character
|
||||
if (currentChar == '\\' && _currentIndex + 1 < _expression.Length)
|
||||
{
|
||||
_currentIndex++;
|
||||
|
||||
if (_expression[_currentIndex] == '\'')
|
||||
{
|
||||
sb.Append('\'');
|
||||
}
|
||||
else if (_expression[_currentIndex] == '\\')
|
||||
{
|
||||
sb.Append('\\');
|
||||
}
|
||||
else if (_expression[_currentIndex] == '/')
|
||||
{
|
||||
sb.Append('/');
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new JsonException(@"Unknown escape character: \" + _expression[_currentIndex]);
|
||||
}
|
||||
|
||||
_currentIndex++;
|
||||
_currentIndex += 2;
|
||||
}
|
||||
else if (currentChar == '/')
|
||||
{
|
||||
sb.Append(currentChar);
|
||||
_currentIndex++;
|
||||
|
||||
string options = ParseRegexOptions();
|
||||
sb.Append(options);
|
||||
while (_currentIndex < _expression.Length)
|
||||
{
|
||||
currentChar = _expression[_currentIndex];
|
||||
|
||||
return sb.ToString();
|
||||
if (char.IsLetter(currentChar))
|
||||
{
|
||||
_currentIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _expression.Substring(startIndex, _currentIndex - startIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentIndex++;
|
||||
sb.Append(currentChar);
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonException("Path ended with an open string.");
|
||||
}
|
||||
|
||||
private string ParseRegexOptions()
|
||||
{
|
||||
var optionsSb = new StringBuilder();
|
||||
|
||||
while (_currentIndex < _expression.Length)
|
||||
{
|
||||
char currentChar = _expression[_currentIndex];
|
||||
|
||||
if (currentChar == 'i'
|
||||
|| currentChar == 'm'
|
||||
|| currentChar == 's'
|
||||
|| currentChar == 'u'
|
||||
|| currentChar == 'x')
|
||||
{
|
||||
_currentIndex++;
|
||||
optionsSb.Append(currentChar);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return optionsSb.ToString();
|
||||
throw new JsonException("Path ended with an open regex.");
|
||||
}
|
||||
|
||||
private bool Match(string s)
|
||||
@@ -827,7 +793,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
|
||||
|
||||
if (Match("=~"))
|
||||
{
|
||||
return QueryOperator.RegExEquals;
|
||||
return QueryOperator.RegexEquals;
|
||||
}
|
||||
|
||||
if (Match("!=") || Match("<>"))
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
|
||||
GreaterThanOrEquals = 7,
|
||||
And = 8,
|
||||
Or = 9,
|
||||
RegExEquals = 10
|
||||
RegexEquals = 10
|
||||
}
|
||||
|
||||
internal abstract class QueryExpression
|
||||
@@ -128,7 +128,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
|
||||
{
|
||||
switch (Operator)
|
||||
{
|
||||
case QueryOperator.RegExEquals:
|
||||
case QueryOperator.RegexEquals:
|
||||
if (RegexEquals(leftValue, rightValue))
|
||||
{
|
||||
return true;
|
||||
@@ -196,7 +196,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
|
||||
return false;
|
||||
}
|
||||
|
||||
var regexText = (string)pattern.Value;
|
||||
string regexText = (string)pattern.Value;
|
||||
int patternOptionDelimiterIndex = regexText.LastIndexOf('/');
|
||||
|
||||
string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
internal static RegexOptions GetRegexOptions(string optionsText)
|
||||
{
|
||||
var options = RegexOptions.None;
|
||||
RegexOptions options = RegexOptions.None;
|
||||
foreach (char c in optionsText)
|
||||
{
|
||||
switch (c)
|
||||
@@ -176,6 +176,5 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user