-Fixed escaping special characters in generated JSONPaths

-Fixed reading escaped special characters in JSONPaths
This commit is contained in:
James Newton-King
2018-01-27 18:39:44 +13:00
parent 0b975a2087
commit 6360cc4c4b
4 changed files with 142 additions and 18 deletions
@@ -0,0 +1,65 @@
#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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
#if DNXCORE50
using Xunit;
using Test = Xunit.FactAttribute;
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
#else
using NUnit.Framework;
#endif
namespace Newtonsoft.Json.Tests.Issues
{
[TestFixture]
public class Issue1592 : TestFixtureBase
{
[Test]
public void Test()
{
string json = @"{
""test customer's"": ""testing""
}";
StringReader stringReader = new StringReader(json);
JsonTextReader reader = new JsonTextReader(stringReader);
reader.Read();
reader.Read();
reader.Read();
Assert.AreEqual("testing", reader.Value);
Assert.AreEqual("['test customer\\'s']", reader.Path);
}
}
}
@@ -34,6 +34,7 @@ using Newtonsoft.Json.Converters;
using Xunit;
using Test = Xunit.FactAttribute;
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
using TestCase = Xunit.InlineDataAttribute;
#else
using NUnit.Framework;
#endif
@@ -1290,5 +1291,37 @@ namespace Newtonsoft.Json.Tests.Linq
ExceptionAssert.Throws<JsonReaderException>(() => JToken.Parse(json),
"Additional text encountered after finished reading JSON content: {. Path '', line 3, position 0.");
}
#if DNXCORE50
[Theory]
#endif
[TestCase("test customer", "['test customer']")]
[TestCase("test customer's", "['test customer\\'s']")]
[TestCase("testcustomer's", "['testcustomer\\'s']")]
[TestCase("testcustomer", "testcustomer")]
[TestCase("test.customer", "['test.customer']")]
[TestCase("test\rcustomer", "['test\\rcustomer']")]
[TestCase("test\ncustomer", "['test\\ncustomer']")]
[TestCase("test\tcustomer", "['test\\tcustomer']")]
[TestCase("test\bcustomer", "['test\\bcustomer']")]
[TestCase("test\fcustomer", "['test\\fcustomer']")]
[TestCase("test/customer", "['test/customer']")]
[TestCase("test\\customer", "['test\\\\customer']")]
[TestCase("\"test\"customer", "['\"test\"customer']")]
public void PathEscapingTest(string name, string expectedPath)
{
JValue v = new JValue("12345");
JObject o = new JObject
{
[name] = v
};
string path = v.Path;
Assert.AreEqual(expectedPath, path);
JToken token = o.SelectToken(path);
Assert.AreEqual(v, token);
}
}
}
+15 -5
View File
@@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using Newtonsoft.Json.Utilities;
@@ -41,7 +42,7 @@ namespace Newtonsoft.Json
internal struct JsonPosition
{
private static readonly char[] SpecialCharacters = { '.', ' ', '[', ']', '(', ')' };
private static readonly char[] SpecialCharacters = { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' };
internal JsonContainerType Type;
internal int Position;
@@ -70,7 +71,7 @@ namespace Newtonsoft.Json
}
}
internal void WriteTo(StringBuilder sb)
internal void WriteTo(StringBuilder sb, ref StringWriter writer, ref char[] buffer)
{
switch (Type)
{
@@ -79,7 +80,14 @@ namespace Newtonsoft.Json
if (propertyName.IndexOfAny(SpecialCharacters) != -1)
{
sb.Append(@"['");
sb.Append(propertyName);
if (writer == null)
{
writer = new StringWriter(sb);
}
JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer);
sb.Append(@"']");
}
else
@@ -122,16 +130,18 @@ namespace Newtonsoft.Json
}
StringBuilder sb = new StringBuilder(capacity);
StringWriter writer = null;
char[] buffer = null;
if (positions != null)
{
foreach (JsonPosition state in positions)
{
state.WriteTo(sb);
state.WriteTo(sb, ref writer, ref buffer);
}
}
if (currentPosition != null)
{
currentPosition.GetValueOrDefault().WriteTo(sb);
currentPosition.GetValueOrDefault().WriteTo(sb, ref writer, ref buffer);
}
return sb.ToString();
+29 -13
View File
@@ -661,28 +661,44 @@ namespace Newtonsoft.Json.Linq.JsonPath
if (currentChar == '\\' && _currentIndex + 1 < _expression.Length)
{
_currentIndex++;
currentChar = _expression[_currentIndex];
if (_expression[_currentIndex] == '\'')
char resolvedChar;
switch (currentChar)
{
sb.Append('\'');
}
else if (_expression[_currentIndex] == '\\')
{
sb.Append('\\');
}
else
{
throw new JsonException(@"Unknown escape character: \" + _expression[_currentIndex]);
case 'b':
resolvedChar = '\b';
break;
case 't':
resolvedChar = '\t';
break;
case 'n':
resolvedChar = '\n';
break;
case 'f':
resolvedChar = '\f';
break;
case 'r':
resolvedChar = '\r';
break;
case '\\':
case '"':
case '\'':
case '/':
resolvedChar = currentChar;
break;
default:
throw new JsonException(@"Unknown escape character: \" + _expression[_currentIndex]);
}
sb.Append(resolvedChar);
_currentIndex++;
}
else if (currentChar == '\'')
{
_currentIndex++;
{
return sb.ToString();
}
return sb.ToString();
}
else
{