I'm trying to load a json file with string values that contain quotes and double quotes.
If I load this file (json ou yaml) and use it in a jinja2 render template, there are errors if I try to load result with a json or a yaml parser.
For example with this json file :
{
"k": "\"v1\"='v2'"
}
Following code fails (with json parser) :
import json
from jinja2 import Environment
j = json.loads('{"k": "\\"v1\\"=\'v2\'"}')
t = Environment().from_string('{{ d }}')
r = t.render({'d': j})
# print(r)=> {'k': '"v1"=\'v2\''}
y = json.loads(r)
with error : json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Or with yaml parser :
import yaml
from jinja2 import Environment
j = yaml.safe_load('{"k": "\\"v1\\"=\'v2\'"}')
t = Environment().from_string('{{ d }}')
r = t.render({'d': j})
# print(r)=> {'k': '"v1"=\'v2\''}
y = yaml.safe_load(r)
this error is returned : yaml.parser.ParserError: while parsing a flow mapping in "<unicode string>", line 1, column 1: {'k': '"v1"=\'v2\''}
I think the error is in my jinja2 render parameters, but how to fix it ?
Note: No problems if I use only double quotes (j = json.loads('{"k": "\\"v1\\""}')
) or only simple quotes (j = json.loads('{"k": "\'v2\'"}')
)
CodePudding user response:
{'k': '"v1"=\'v2\''}
is neither valid JSON nor YAML. This is because JSON exclusively supports double-quoted strings, and YAML does support single-quoted strings but those do not process escape sequences.
Jinja renders it this way because it is valid Python. Jinja does not know you want to parse it as JSON or YAML. You have to serialize the structure as JSON if you want to load it as JSON again later:
import json
from jinja2 import Environment
j = json.loads('{"k": "\\"v1\\"=\'v2\'"}')
t = Environment().from_string('{{ d }}')
r = t.render({'d': json.dumps(j)})
# print(r)=> {"k": "\"v1\"='v2'"}
y = json.loads(r)
print(y)
As you can see, I replaced j
with json.dumps(j)
so that Jinja will output proper JSON – you can see that r
now contains two double-quoted strings.
In this example, you wouldn't even need to load the original string into j
as you can just pass it directly to Jinja, but I assume you want to modify the data before passing it into the template.