tera icon indicating copy to clipboard operation
tera copied to clipboard

Ability to build an object or hashmap?

Open absolutejam opened this issue 1 year ago • 8 comments

Hey!

I'm trying to build some grouping functionality for my Zola blog and I wondered if it is currently possible (or planned) to build and mutate a JSON object or hashmap data structure?

For example, I'm currently iterating over an array of objects that each have their own tags. I'd like to be able to group these objects into by their tags, ending up with a Hashmap<String, Vec<MyObject>> in rough Rust terms.

It looks like this would probably want to live in https://github.com/Keats/tera/blob/master/src/builtins/filters/object.rs as this is already concerned with handling serde_json::Value::Objects?

I'm happy to take a stab at this if you're okay with it 👍

absolutejam avatar Feb 08 '24 22:02 absolutejam

This will be tremendously interesting to me. It will drastically reduce the number of parameters I have in macros and simplify a lot of code if optional fields can be grouped inside a single config object instead of each being a variable.

A way to create a hash literal is needed as well as the ability to set a field of an object.

schungx avatar Apr 20 '24 06:04 schungx

@absolutejam your suggestion gives me an idea.

We can very simply write such a function, say make_obj, that returns a hash object from its parameters.

Until the native syntax arrives, this can be a huge boom in productivity as I can then write macros that take objects as parameters.

EDIT: I confirm that the idea works. I have obj function and mixin/polyfill filters and all are looking good!

schungx avatar Apr 20 '24 06:04 schungx

What's not defined yet is what would be the syntax to update a hashmap

Keats avatar Apr 20 '24 20:04 Keats

I solved it via a mixin filter:

{{ map | mixin(foo=42, bar=true) }}

will return a new map with the two properties replaced.

Setting properties then become:

set map = map | mixin(foo=42, bar=true)

schungx avatar Apr 22 '24 06:04 schungx

Yeah the filter is the obvious one, it's just a bit verbose to set new things but maybe it's the simpler one

Keats avatar Apr 23 '24 20:04 Keats

If you're looking for syntax suggestions, I suggest:

{% set_prop map.foo = 42 %}
{% set_prop map["foo"] = 42 %}

{% remove_prop map.foo %}
{% remove_prop map["foo"] %}

schungx avatar May 01 '24 10:05 schungx

Or maybe just {% set map.foo = 42 %}? I don't know if we will need to remove things from a hashmap. I have never needed that in any template engine (so far)

Keats avatar May 03 '24 18:05 Keats

Or maybe just {% set map.foo = 42 %}? I don't know if we will need to remove things from a hashmap. I have never needed that in any template engine (so far)

That would work too...

In that case we can do delete map.prop or delete_prop map.prop like JavaScript.

schungx avatar May 04 '24 09:05 schungx