Pablo Matias Gomez
Pablo Matias Gomez

Reputation: 6823

Assign key for a hash inside a hash in freemarker

I want to make a new model of an existing model in freemarker to make it easy to use.

My model is something like this:

[
    {
        "id": "1",
        "type": "TYPE_1",
        "code": "CODE_OF_TYPE_1"
    },
    {
        "id": "2",
        "type": "TYPE_1",
        "code": "ANOTHER_CODE_OF_TYPE_1"
    },
    {
        "id": "3",
        "type": "TYPE_2",
        "code": "CODE_OF_TYPE_2"
    },
    {
        "id": "4",
        "type": "TYPE_2",
        "code": "ANOTHER_CODE_OF_TYPE_2"
    }
]

And I want to make it something like this:

 {
    "TYPE_1": {
        "CODE_OF_TYPE_1": "1",
        "ANOTHER_CODE_OF_TYPE_1": "2"
    },
    "TYPE_2": {
        "CODE_OF_TYPE_2": "3",
        "ANOTHER_CODE_OF_TYPE_2": "4"
    }
}

As you may know, assigning a key for a hash in freemarker is a little strange..

What I did was this:

<#assign preferencesByCode = {} />

<#list preferences as preference>
    <assign preferencesByCode = preferencesByCode + {preference.type : { preference.code: preference.id } } />
</#list>

But doing that, it only keeps the last id, so I only have one type..

So then I tried this:

<#if !(preferencesByCode[preference.type])??>
    <#assign preferencesByCode = preferencesByCode + {preference.type : { } } />
</#if>

<#assign subHash = preferencesByCode[preference.type] />
<#assign subHash = subHash + {preference.code : preference.id } />

But the subHash is not kept as a reference so anything is being asigned to the type..

Any ideas?

Upvotes: 5

Views: 9148

Answers (2)

Moesio
Moesio

Reputation: 3178

A freemarker function returning last hash value from a root object in some path

<#function deepHash obj path>
    <#assign hashes = path?split(".")>
    <#assign value = obj/>
    <#list hashes as hash>
        <#assign value = value[hash]!/>
    </#list>
    <#if value?is_boolean>
        <#return value?c>
    <#else>
        <#return value>
    </#if>
</#function>

Exemple: if an object is

item 
    {
    "some": 
            {
        "thing": 
            {
                "deep": "Gotta",
            }
        }
    }


<#assign value = deepHash(item, "some.thing.deep") />
${value}

will show:

Gotta

Upvotes: 0

YetAnotherFrank
YetAnotherFrank

Reputation: 406

While I agree with @ddekany's comment, here is a solution for your problem.

<#function filterList list type>
  <#local result={}>
  <#list list as preference>
    <#if preference.type == type>
      <#local result=result + {
        preference.code: preference.id
      }>
    </#if>
  </#list>
  <#return result>
</#function>

<#function convertList list>
  <#local result={}>
  <#list list as preference>
    <#if !result[preference.type]??>
      <#local result=result + { preference.type: filterList(list, preference.type) }>
    </#if>
  </#list>
  <#return result>
</#function>

<#assign transformedModel=convertList(model)>

Upvotes: 7

Related Questions