Replies: 3 comments 5 replies
-
I agree that if the user generates a JSON we should keep that a string rather than cast it back to pure Python. Note this would already happen if the JSON blob contains |
Beta Was this translation helpful? Give feedback.
-
This is a weird corner case, but I'm not sure what the solution should be yet. This is also very similar to this issue: #917. Copying my comment from the linked Ansible issue:
|
Beta Was this translation helpful? Give feedback.
-
This discussion split from here to Discord. I'm copying back my answer from Discord. Basically, the problem is that the built-in It's perfectly fine to override the filter in that case to suit the needs of that environment. All that needs to be done is to surround the produced string with single quotes. You can even reuse the existing filter. Calling from jinja2.filters import do_tojson
@pass_eval_context
def do_tojson_str(eval_ctx, value):
return f"'{str(do_tojson(eval_ctx, value))}'"
env.filters["tojson"] = do_tojson_str |
Beta Was this translation helpful? Give feedback.
-
If I understand correctly, when
NativeEnvironment
was added, the idea was to leverage most of the commonCodeGenerator
/NodeVisitor
with slight changes to rendering child AST nodes. The aim was to then subsequently pass the return of the generated python code intoast.literal_eval
. If it succeeded it was representative of a native Python object.An issue my team has come across several times is with how NativeEnvironment handles the result of the
tojson
filter. For example:{{some_global|tojson}}
. This would return a str successfully iff the parameter to the filter has either a JSON boolean (lowercase true|false) or null. Without these values in the parameter, literal_eval would successfully parse the str to a Python list or dict.Upon further inspection, the result of this single Node result is of type
Markup
from the MarkupSafe library.Recently in parallel, with Python 3.10, a fix was added to have some conditional on the result here:
jinja/src/jinja2/nativetypes.py
Line 32 in 0d17780
My proposal is to add an additional
isinstance
check to the same line of code to return raw:My main point here is why should we be evaluating anything that is already escaped into Markup? And the added benefit is a more sane approach to the result of
tojson
.There are some limitations here, in that this still would not work with constants, e.g.
{{{'a': 1}|tojson}}
as Jinja will try to compile this static expression to a str directly (because only expressions that evaluate at runtime thrownodes.Impossible()
). I'm sure we could rework the_output_to_child_const
code path to solve this as well. If an expression results in Markup which is already a sublcass of str there is no need to convert it to a constant (it already is one).Beta Was this translation helpful? Give feedback.
All reactions