Skip to content

serialize (10)

deserialize

deserialize(data: str, fmt: Literal['yaml', 'json', 'ini', 'toml'], **kwargs: Any) -> Any

Serialize given json-like object to given format.

Example

Jinja call:

{{ "[abc.def]
value = 1" | deserialize("toml") }}
Result: {'abc': {'def': {'value': 1}}}

DocStrings

Parameters:

Name Type Description Default
data str

The data to deserialize

required
fmt SerializeFormatStr

The serialization format

required
kwargs Any

Keyword arguments passed to the loader function

{}
Source code in src/jinjarope/serializefilters.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
def deserialize(data: str, fmt: SerializeFormatStr, **kwargs: Any) -> Any:
    """Serialize given json-like object to given format.

    Args:
        data: The data to deserialize
        fmt: The serialization format
        kwargs: Keyword arguments passed to the loader function
    """
    match fmt:
        case "yaml":
            import yamling

            return yamling.load_yaml(data, **kwargs)
        case "json":
            return json.loads(data, **kwargs)
        case "ini":
            return load_ini(data, **kwargs)
        case "toml":
            import tomllib

            return tomllib.loads(data, **kwargs)
        case _:
            raise TypeError(fmt)

dictsort

dictsort(value: Mapping[~K, ~V], case_sensitive: bool = False, by: 'te.Literal["key", "value"]' = 'key', reverse: bool = False) -> List[Tuple[~K, ~V]]

Sort a dict and yield (key, value) pairs. Python dicts may not

Example

Jinja call:

{{ {"b": 1, "a": 2} | dictsort }}
Result: [('a', 2), ('b', 1)]

Example

Jinja call:

{{ {"b": 1, "a": 2} | dictsort(by="value") }}
Result: [('b', 1), ('a', 2)]

DocStrings
Source code in .venv/lib/python3.12/site-packages/jinja2/filters.py
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
def do_dictsort(
    value: t.Mapping[K, V],
    case_sensitive: bool = False,
    by: 'te.Literal["key", "value"]' = "key",
    reverse: bool = False,
) -> t.List[t.Tuple[K, V]]:
    """Sort a dict and yield (key, value) pairs. Python dicts may not
    be in the order you want to display them in, so sort them first.

    .. sourcecode:: jinja

        {% for key, value in mydict|dictsort %}
            sort the dict by key, case insensitive

        {% for key, value in mydict|dictsort(reverse=true) %}
            sort the dict by key, case insensitive, reverse order

        {% for key, value in mydict|dictsort(true) %}
            sort the dict by key, case sensitive

        {% for key, value in mydict|dictsort(false, 'value') %}
            sort the dict by value, case insensitive
    """
    if by == "key":
        pos = 0
    elif by == "value":
        pos = 1
    else:
        raise FilterArgumentError('You can only sort by either "key" or "value"')

    def sort_func(item: t.Tuple[t.Any, t.Any]) -> t.Any:
        value = item[pos]

        if not case_sensitive:
            value = ignore_case(value)

        return value

    return sorted(value.items(), key=sort_func, reverse=reverse)

dig

dig(data: dict, *sections: str, keep_path: bool = False, dig_yaml_lists: bool = True) -> Any

Try to get data with given section path from a dict-list structure.

Example

Jinja call:

{{ {"section1": {"section2": {"section3": "Hello, World"} } } | dig("section1", "section2") }}
Result: {'section3': 'Hello, World'}

Example

Jinja call:

{{ {"section1": {"section2": {"section3": "Hello, World"} } } | dig("section1", "section2", keep_path=True) }}
Result: {'section1': {'section2': {'section3': 'Hello, World'}}}

DocStrings

Parameters:

Name Type Description Default
data dict

The data to dig into

required
sections str

Sections to dig into

()
keep_path bool

Return result with original nesting

False
dig_yaml_lists bool

Also dig into single-key->value pairs, as often found in yaml.

True
Source code in src/jinjarope/serializefilters.py
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
def dig(
    data: dict,
    *sections: str,
    keep_path: bool = False,
    dig_yaml_lists: bool = True,
) -> Any:
    """Try to get data with given section path from a dict-list structure.

    If a list is encountered and dig_yaml_lists is true, treat it like a list of
    {"identifier", {subdict}} items, as used in MkDocs config for
    plugins & extensions.
    If Key path does not exist, return None.

    Args:
        data: The data to dig into
        sections: Sections to dig into
        keep_path: Return result with original nesting
        dig_yaml_lists: Also dig into single-key->value pairs, as often found in yaml.
    """
    for i in sections:
        if isinstance(data, dict):
            if child := data.get(i):
                data = child
            else:
                return None
        elif dig_yaml_lists and isinstance(data, list):
            # this part is for yaml-style listitems
            for idx in data:
                if i in idx and isinstance(idx, dict):
                    data = idx[i]
                    break
                if isinstance(idx, str) and idx == i:
                    data = idx
                    break
            else:
                return None
    if not keep_path:
        return data
    result: dict[str, dict] = {}
    new = result
    for sect in sections:
        result[sect] = data if sect == sections[-1] else {}
        result = result[sect]
    return new

dump_json

dump_json(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

Serialize obj to a JSON formatted str.

Example

Jinja call:

{{ {'a': 'b'} | dump_json }}
Result: {"a": "b"}

DocStrings
Source code in json/__init__.py
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):
    """Serialize ``obj`` to a JSON formatted ``str``.

    If ``skipkeys`` is true then ``dict`` keys that are not basic types
    (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
    instead of raising a ``TypeError``.

    If ``ensure_ascii`` is false, then the return value can contain non-ASCII
    characters if they appear in strings contained in ``obj``. Otherwise, all
    such characters are escaped in JSON strings.

    If ``check_circular`` is false, then the circular reference check
    for container types will be skipped and a circular reference will
    result in an ``RecursionError`` (or worse).

    If ``allow_nan`` is false, then it will be a ``ValueError`` to
    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
    strict compliance of the JSON specification, instead of using the
    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).

    If ``indent`` is a non-negative integer, then JSON array elements and
    object members will be pretty-printed with that indent level. An indent
    level of 0 will only insert newlines. ``None`` is the most compact
    representation.

    If specified, ``separators`` should be an ``(item_separator, key_separator)``
    tuple.  The default is ``(', ', ': ')`` if *indent* is ``None`` and
    ``(',', ': ')`` otherwise.  To get the most compact JSON representation,
    you should specify ``(',', ':')`` to eliminate whitespace.

    ``default(obj)`` is a function that should return a serializable version
    of obj or raise TypeError. The default simply raises TypeError.

    If *sort_keys* is true (default: ``False``), then the output of
    dictionaries will be sorted by key.

    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
    ``.default()`` method to serialize additional types), specify it with
    the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.

    """
    # cached encoder
    if (not skipkeys and ensure_ascii and
        check_circular and allow_nan and
        cls is None and indent is None and separators is None and
        default is None and not sort_keys and not kw):
        return _default_encoder.encode(obj)
    if cls is None:
        cls = JSONEncoder
    return cls(
        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
        separators=separators, default=default, sort_keys=sort_keys,
        **kw).encode(obj)

items

items(value: Union[Mapping[~K, ~V], jinja2.runtime.Undefined]) -> Iterator[Tuple[~K, ~V]]

Return an iterator over the (key, value) items of a mapping.

Example

Jinja call:

{{ {"a": "b"} | items }}
Result: <generator object do_items at 0x7f828052f780>

Example

Jinja call:

{{ {"a": {"b": "c"}} | items | list }}
Result: [('a', {'b': 'c'})]

DocStrings
Source code in .venv/lib/python3.12/site-packages/jinja2/filters.py
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K, V]]:
    """Return an iterator over the ``(key, value)`` items of a mapping.

    ``x|items`` is the same as ``x.items()``, except if ``x`` is
    undefined an empty iterator is returned.

    This filter is useful if you expect the template to be rendered with
    an implementation of Jinja in another programming language that does
    not have a ``.items()`` method on its mapping type.

    .. code-block:: html+jinja

        <dl>
        {% for key, value in my_dict|items %}
            <dt>{{ key }}
            <dd>{{ value }}
        {% endfor %}
        </dl>

    .. versionadded:: 3.1
    """
    if isinstance(value, Undefined):
        return

    if not isinstance(value, abc.Mapping):
        raise TypeError("Can only get item pairs from a mapping.")

    yield from value.items()

load_json

load_json(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

Deserialize s (a str, bytes or bytearray instance

Example

Jinja call:

{{ "[1, 2]" | load_json }}
Result: [1, 2]

DocStrings
Source code in json/__init__.py
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
def loads(s, *, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance
    containing a JSON document) to a Python object.

    ``object_hook`` is an optional function that will be called with the
    result of any object literal decode (a ``dict``). The return value of
    ``object_hook`` will be used instead of the ``dict``. This feature
    can be used to implement custom decoders (e.g. JSON-RPC class hinting).

    ``object_pairs_hook`` is an optional function that will be called with the
    result of any object literal decoded with an ordered list of pairs.  The
    return value of ``object_pairs_hook`` will be used instead of the ``dict``.
    This feature can be used to implement custom decoders.  If ``object_hook``
    is also defined, the ``object_pairs_hook`` takes priority.

    ``parse_float``, if specified, will be called with the string
    of every JSON float to be decoded. By default this is equivalent to
    float(num_str). This can be used to use another datatype or parser
    for JSON floats (e.g. decimal.Decimal).

    ``parse_int``, if specified, will be called with the string
    of every JSON int to be decoded. By default this is equivalent to
    int(num_str). This can be used to use another datatype or parser
    for JSON integers (e.g. float).

    ``parse_constant``, if specified, will be called with one of the
    following strings: -Infinity, Infinity, NaN.
    This can be used to raise an exception if invalid JSON numbers
    are encountered.

    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
    kwarg; otherwise ``JSONDecoder`` is used.
    """
    if isinstance(s, str):
        if s.startswith('\ufeff'):
            raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",
                                  s, 0)
    else:
        if not isinstance(s, (bytes, bytearray)):
            raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                            f'not {s.__class__.__name__}')
        s = s.decode(detect_encoding(s), 'surrogatepass')

    if (cls is None and object_hook is None and
            parse_int is None and parse_float is None and
            parse_constant is None and object_pairs_hook is None and not kw):
        return _default_decoder.decode(s)
    if cls is None:
        cls = JSONDecoder
    if object_hook is not None:
        kw['object_hook'] = object_hook
    if object_pairs_hook is not None:
        kw['object_pairs_hook'] = object_pairs_hook
    if parse_float is not None:
        kw['parse_float'] = parse_float
    if parse_int is not None:
        kw['parse_int'] = parse_int
    if parse_constant is not None:
        kw['parse_constant'] = parse_constant
    return cls(**kw).decode(s)

load_toml

load_toml(s: str, /, *, parse_float: Callable[[str], Any] = <class 'float'>) -> dict[str, typing.Any]

Parse TOML from a string.

Example

Jinja call:

{{ "[abc]
b=1" | load_toml }}
Result: {'abc': {'b': 1}}

DocStrings
Source code in tomllib/_parser.py
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def loads(s: str, /, *, parse_float: ParseFloat = float) -> dict[str, Any]:  # noqa: C901
    """Parse TOML from a string."""

    # The spec allows converting "\r\n" to "\n", even in string
    # literals. Let's do so to simplify parsing.
    src = s.replace("\r\n", "\n")
    pos = 0
    out = Output(NestedDict(), Flags())
    header: Key = ()
    parse_float = make_safe_parse_float(parse_float)

    # Parse one statement at a time
    # (typically means one line in TOML source)
    while True:
        # 1. Skip line leading whitespace
        pos = skip_chars(src, pos, TOML_WS)

        # 2. Parse rules. Expect one of the following:
        #    - end of file
        #    - end of line
        #    - comment
        #    - key/value pair
        #    - append dict to list (and move to its namespace)
        #    - create dict (and move to its namespace)
        # Skip trailing whitespace when applicable.
        try:
            char = src[pos]
        except IndexError:
            break
        if char == "\n":
            pos += 1
            continue
        if char in KEY_INITIAL_CHARS:
            pos = key_value_rule(src, pos, out, header, parse_float)
            pos = skip_chars(src, pos, TOML_WS)
        elif char == "[":
            try:
                second_char: str | None = src[pos + 1]
            except IndexError:
                second_char = None
            out.flags.finalize_pending()
            if second_char == "[":
                pos, header = create_list_rule(src, pos, out)
            else:
                pos, header = create_dict_rule(src, pos, out)
            pos = skip_chars(src, pos, TOML_WS)
        elif char != "#":
            raise suffixed_err(src, pos, "Invalid statement")

        # 3. Skip comment
        pos = skip_comment(src, pos)

        # 4. Expect end of line or end of file
        try:
            char = src[pos]
        except IndexError:
            break
        if char != "\n":
            raise suffixed_err(
                src, pos, "Expected newline or end of document after a statement"
            )
        pos += 1

    return out.data.dict

merge

merge(target: 'list | dict', *source: 'list | dict', deepcopy: 'bool' = False, mergers: 'dict[type, Callable[[Any, Any, Any], Any]] | None' = None) -> 'list | dict'

Merge given data structures using mergers provided.

Example

Jinja call:

{{ {"a": {"b": 1} } | merge({"a": {"c": 2} }) }}
Result: {'a': {'b': 1, 'c': 2}}

DocStrings

Parameters:

Name Type Description Default
target list | dict

Data structure to merge into

required
source list | dict

Data structures to merge into target

()
deepcopy bool

Whether to deepcopy the target

False
mergers dict[type, Callable[[Any, Any, Any], Any]] | None

Mergers with strategies for each type (default: additive)

None
Source code in src/jinjarope/serializefilters.py
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def merge(
    target: list | dict,
    *source: list | dict,
    deepcopy: bool = False,
    mergers: dict[type, Callable[[Any, Any, Any], Any]] | None = None,
) -> list | dict:
    """Merge given data structures using mergers provided.

    Args:
        target: Data structure to merge into
        source:  Data structures to merge into target
        deepcopy: Whether to deepcopy the target
        mergers: Mergers with strategies for each type (default: additive)
    """
    import copy

    if deepcopy:
        target = copy.deepcopy(target)
    context = deepmerge.DeepMerger(mergers)
    for s in source:
        target = context.merge(s, target)
    return target

serialize

serialize(data: Any, fmt: Literal['yaml', 'json', 'ini', 'toml'], **kwargs: Any) -> str

Serialize given json-like object to given format.

Example

Jinja call:

{{ {"a": "b"} | serialize("toml") }}
Result: a = "b"

DocStrings

Parameters:

Name Type Description Default
data Any

The data to serialize

required
fmt SerializeFormatStr

The serialization format

required
kwargs Any

Keyword arguments passed to the dumper function

{}
Source code in src/jinjarope/serializefilters.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def serialize(data: Any, fmt: SerializeFormatStr, **kwargs: Any) -> str:
    """Serialize given json-like object to given format.

    Args:
        data: The data to serialize
        fmt: The serialization format
        kwargs: Keyword arguments passed to the dumper function
    """
    match fmt:
        case "yaml":
            import yamling

            return yamling.dump_yaml(data, **kwargs)
        case "json":
            return json.dumps(data, indent=4, **kwargs)
        case "ini":
            config = configparser.ConfigParser(**kwargs)
            config.read_dict(data)
            file = io.StringIO()
            with file as fp:
                config.write(fp)
                return file.getvalue()
        case "toml" if isinstance(data, dict):
            import tomli_w

            return tomli_w.dumps(data, **kwargs)
        case _:
            raise TypeError(fmt)

tojson

tojson(eval_ctx: 'EvalContext', value: Any, indent: Optional[int] = None) -> markupsafe.Markup

Serialize an object to a string of JSON, and mark it safe to

Example

Jinja call:

{{ "[1, 2]" | tojson }}
Result: "[1, 2]"

Example

Jinja call:

{{ {"nested": {"data": [1,2]}} | tojson(indent=2) }}
Result: { "nested": { "data": [ 1, 2 ] } }

DocStrings
Source code in .venv/lib/python3.12/site-packages/jinja2/filters.py
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
@pass_eval_context
def do_tojson(
    eval_ctx: "EvalContext", value: t.Any, indent: t.Optional[int] = None
) -> Markup:
    """Serialize an object to a string of JSON, and mark it safe to
    render in HTML. This filter is only for use in HTML documents.

    The returned string is safe to render in HTML documents and
    ``<script>`` tags. The exception is in HTML attributes that are
    double quoted; either use single quotes or the ``|forceescape``
    filter.

    :param value: The object to serialize to JSON.
    :param indent: The ``indent`` parameter passed to ``dumps``, for
        pretty-printing the value.

    .. versionadded:: 2.9
    """
    policies = eval_ctx.environment.policies
    dumps = policies["json.dumps_function"]
    kwargs = policies["json.dumps_kwargs"]

    if indent is not None:
        kwargs = kwargs.copy()
        kwargs["indent"] = indent

    return htmlsafe_json_dumps(value, dumps=dumps, **kwargs)