Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion jsonschema/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from textwrap import dedent, indent
from typing import TYPE_CHECKING, Any, ClassVar
import heapq
import re
import warnings

from attrs import define
Expand All @@ -23,6 +24,8 @@
WEAK_MATCHES: frozenset[str] = frozenset(["anyOf", "oneOf"])
STRONG_MATCHES: frozenset[str] = frozenset()

JSON_PATH_COMPATIBLE_PROPERTY_PATTERN = re.compile("^[a-zA-Z][a-zA-Z0-9_]*$")

_unset = _utils.Unset()


Expand Down Expand Up @@ -152,8 +155,11 @@ def json_path(self) -> str:
for elem in self.absolute_path:
if isinstance(elem, int):
path += "[" + str(elem) + "]"
else:
elif JSON_PATH_COMPATIBLE_PROPERTY_PATTERN.match(elem):
path += "." + elem
else:
escaped_elem = elem.replace("\\", "\\\\").replace("'", r"\'")
path += "['" + escaped_elem + "']"
return path

def _set(
Expand Down
119 changes: 119 additions & 0 deletions jsonschema/tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,3 +700,122 @@ class TestHashable(TestCase):
def test_hashable(self):
{exceptions.ValidationError("")}
{exceptions.SchemaError("")}


class TestJsonPathRendering(TestCase):
def test_str(self):
e = exceptions.ValidationError(
path=["x"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$.x")

def test_empty_str(self):
e = exceptions.ValidationError(
path=[""],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$['']")

def test_numeric_str(self):
e = exceptions.ValidationError(
path=["1"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$['1']")

def test_period_str(self):
e = exceptions.ValidationError(
path=["."],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$['.']")

def test_single_quote_str(self):
e = exceptions.ValidationError(
path=["'"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, r"$['\'']")

def test_space_str(self):
e = exceptions.ValidationError(
path=[" "],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$[' ']")

def test_backslash_str(self):
e = exceptions.ValidationError(
path=["\\"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, r"$['\\']")

def test_backslash_single_quote(self):
e = exceptions.ValidationError(
path=[r"\'"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, r"$['\\\'']")

def test_underscore(self):
e = exceptions.ValidationError(
path=["_"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, r"$['_']")

def test_double_quote(self):
e = exceptions.ValidationError(
path=['"'],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, """$['"']""")

def test_hyphen(self):
e = exceptions.ValidationError(
path=["-"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$['-']")

def test_json_path_injection(self):
e = exceptions.ValidationError(
path=["a[0]"],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$['a[0]']")

def test_open_bracket(self):
e = exceptions.ValidationError(
path=["["],
message="1",
validator="foo",
instance="i1",
)
self.assertEqual(e.json_path, "$['[']")
Loading