Skip to content

Commit

Permalink
Restore support for legacy unquoted string literals
Browse files Browse the repository at this point in the history
While we definitely want to transition away from unquoted string
literals, it seems reasonable to do that over time, similarly to how it
was handled in jmespath.py.

The reason for doing so, is to allow for a simple upgrade path, where a
new version of jmespath.rb can be installed, and the software using it
can transition all its configuration to use the new format, and then the
jmespath.rb version could be upgraded to not even support these
expressions.

The tests were copied verbatim from jmespath.py, and are not included in
the compliance test suite, so comes with an explicit license, which the
compliance test suite does not. JSON doesn't allow for comments, so I'm
not sure how to handle the attribution clause of the jmespath.py license
  • Loading branch information
grddev committed May 23, 2016
1 parent bd47690 commit 95ac4b0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 4 deletions.
10 changes: 7 additions & 3 deletions lib/jmespath/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def tokenize(expression)
token = inside(chars, '"', T_QUOTED_IDENTIFIER)
if token.type == T_QUOTED_IDENTIFIER
token.value = "\"#{token.value}\""
token = parse_json(token)
token = parse_json(token, true)
end
tokens << token
when STATE_EQ
Expand Down Expand Up @@ -295,9 +295,13 @@ def inside(chars, delim, type)
Token.new(type, buffer.join, position)
end

def parse_json(token)
def parse_json(token, quoted=false)
begin
token.value = JSON.load(token.value)
if quoted
token.value = JSON.load(token.value)
else
token.value = JSON.load(token.value) rescue JSON.load(sprintf('"%s"', token.value.lstrip))
end
rescue JSON::ParserError
token.type = T_UNKNOWN
end
Expand Down
2 changes: 1 addition & 1 deletion spec/compliance_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
SimpleCov.command_name('test:compliance')

describe 'Compliance' do
Dir.glob('spec/compliance/*.json').each do |path|
Dir.glob('spec/{compliance,legacy}/*.json').each do |path|

test_file = File.basename(path).split('.').first
next if test_file == 'benchmarks'
Expand Down
56 changes: 56 additions & 0 deletions spec/legacy/literal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[
{
"given": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "`foo`",
"result": "foo"
},
{
"comment": "Double quotes must be escaped.",
"expression": "`foo\\\"quote`",
"result": "foo\"quote"
},
{
"expression": "`✓`",
"result": ""
},
{
"comment": "Double quote in literal",
"expression": "`foo\\\"bar`",
"result": "foo\"bar"
},
{
"expression": "`1\\``",
"result": "1`"
},
{
"comment": "Multiple literal expressions with escapes",
"expression": "`\\\\`.{a:`b`}",
"result": {"a": "b"}
}
]
},
{
"comment": "Literals",
"given": {"type": "object"},
"cases": [
{
"expression": "`foo`",
"result": "foo"
},
{
"expression": "` foo`",
"result": "foo"
},
{
"comment": "Literal on RHS of subexpr not allowed",
"expression": "foo.`bar`",
"error": "syntax"
}
]
}
]

0 comments on commit 95ac4b0

Please sign in to comment.