Julien B.
Julien B.

Reputation: 3334

Twig merge for json with string of numbers as key

I'm trying to merge hashes with Twig to output JSON.

My problem is that some of my keys are using strings of numbers and twig converts it to integers.

My code :

{% set rows = {} %}
{% for key, val in row %}
    {% set rows = rows|merge({ (key) : val }) %}
{% endfor %}
{{ { 'report': { 'metric': metric, 'rows': rows, 'tot': tot, 'min': min, 'max': max } }|json_encode|raw }}

Which outputs

{"report":{"metric":"sessions","rows":["5","4","4","3","7","4","4"],"tot":"31","min":"0","max":"7"}}

I also tried replacing my keys with number_format, but since I'm stripping all non-numeric characters, the output is the same.

{% set rows = {} %}
{% for key, val in row %}
    {% set rows = rows|merge({ (key)|number_format(0,'','') : val }) %}
{% endfor %}
{{ { 'report': { 'metric': metric, 'rows': rows, 'tot': tot, 'min': min, 'max': max } }|json_encode|raw }}

The result expected goes like this:

{"report":{"metric":"sessions","rows":{"20180423":"5","20180424":"4","20180425":"4","20180426":"3","20180427":"7","20180428":"4","20180429":"4"},"tot":"31","min":"0","max":"7"}}

Is there any way I can prevent Twig from changing my keys to integers?

Found this post, but it doesn't work for me since my keys are strings of numbers. key value being replaced by 'key' when using merge() in twig

Upvotes: 0

Views: 1957

Answers (1)

Philippe-B-
Philippe-B-

Reputation: 636

Twig's merge filter relies on PHP's array_merge function and the doc says :

Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.

And string containing only numbers are considered numeric.

Solution:

The simplest solution would be to change the keys format from "20180423" to "2018-04-23" which would make it non-numeric.


If you really need to keep your numeric keys, you could create a custom filter to merge arrays the way you want:

namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class AppExtension extends AbstractExtension
{
    public function getFilters()
    {
        return array(
            new TwigFilter('mymerge', array($this, 'merge')),
        );
    }

    public function merge($baseArray, $arrayToMerge)
    {
        foreach ($arrayToMerge as $key => $value) {
            $baseArray[$key] = $value;
        }

        return $baseArray;
    }
}

Then

{% set test = {"1234": "2", "2345": "3"} %}
{% set rows = {"test": "1"} %}
{% set rows = rows|mymerge(test) %}
{{ { 'report': { 'rows': rows } }|json_encode|raw }}

Would output

{"report":{"rows":{"test":"1","1234":"2","2345":"3"}}}

Upvotes: 3

Related Questions