Forum Discussion

SheryBulos's avatar
5 years ago

how to parse json file in the assets?

Hello everyone,

I am trying to get json file content in the component to be passed as a parameter to macro,
so how can this be achieved?

PS. the file exists in the studio assets

I tried <#assign doc=asset.get("/html/assets/products.json") > however this didn't work?

Thanks in advance,
Shery

  • Hello SheryBulos ,

    <#assign data=asset.get("/html/assets/test.json") >
    ${data}

    <script>

    var data = "${data}";
    fetch(data).then(res => res.json()).then(data => console.log(data, "data"))

    </script>


    Obtaining data from a JSON asset file and sharing the screenshot for your reference. Hope this information may help with your requirement.

     

  • Unfortunately manasab 's way is the only way to do what you asked for without changing your approach. But as you can see, it requires JS to fetch the file and parse it, which might not be what you want if you want to use the JSON data within Freemarker. This is because asset.get() only returns a URL to the static file and not its content (that might also be a bit misleading in the code manasab posted as he labelled it "data", which is technically not true, it's just a URL). There is afaik no way of doing a "read-file" operation within Freemarker. If you want to use your JSON data within Freemarker you'll have to change the way you store the JSON data, there are a few options:

    1. Use a separate component to store the JSON string, so it is separated from the logic, then you can simply "dumb import" that component into your logic component and parse the JSON there with Freemarker so you get a Freemarker hash to work with. => this is roughly similar in terms of "inconvenience" to the static asset/file you uploaded, both reside in studio and cannot be changed on production without re-deploying.

    To illustrate, an example:

    Let's assume you have your logic and JSON data separated in two components

    - json.component => the logic
    - json.component.data => the JSON data

    then in your json.component you do this:

     

    <#assign json>
    	<@component id="json.component.data" />
    	<#-- contains something like:
    	[
    		{
    			"title": "Apple iPhone 13"
    		},
    		{
    			"title": "Apple iPhone 8"
    		}
    	]
    	-->
    </#assign>
    
    <#assign data = utils.json.fromJson(json?is_markup_output?then(json?markup_string, json)) />
    
    <#list data as obj>
    	${obj.title}
    </#list>

     


    2. A slightly different approach using custom content fields which you can edit also on production and get context "per node" for free (values are inherited from higher level nodes except their value is overwritten locally). I recommend this approach except you have a specific requirement to make the JSON not changeable on prod, e.g. you want it needing a re-deployment to publish changes! Alternatively you can ask support for a custom node level field that you can access the same way, it can be hidden from the Admin UI and/or is not in the same place as custom content fields. I'm assuming here that the JSON is stored in custom content 2:

     

    <#assign json = coreNode.settings.name.get('customcontent.2_text', '[]') />
    <#assign data = utils.json.fromJson(json?is_markup_output?then(json?markup_string, json)) />
    
    <#list data as obj>
    	${obj.title}
    </#list>

     


    3. You could also put the JSON into a macro and "properly" import it in FreeMarker, but I don't think that's very practical as the JSON data will live somewhere where noone expects it apart from the component logic and you do not gain any benefits over the approach outlined in 1.