[SOLVED] Loading JSON data file as a resource


#1

I have a JSON file stored in content/operating-areas/areas.json. There’s also an index.md within the operating-areas folder.

I am trying to load the areas.json file as a resource like so:

{{ with .Site.GetPage "operating-areas/index.md" }}
<section class="uk-section operating-areas">
  <div>
    <h2 class="uk-text-lead uk-text-center"><span>{{ .Title }}</span></h2>
    {{ with .Content }}
    <p class="uk-text-center">{{- . -}}</p>
    {{ end }}
  </div>

  <ul>
    {{ with .Resources.GetMatch "areas.json" }}
    {{ range .areas }}
    <li>{{ . }}<li>
    {{ end }}
    {{ end }}
  </ul>
</section>
{{ end }}

My JSON file:

{
    "areas": [
        "London",
        "Manchester",
        ...
    ]
}

But I’m getting an error:

Building sites … ERROR 2018/11/09 19:25:04 Error while rendering "home" in "": template: index.html:7:5: executing "main" at <partial "operating-a...>: error calling partial: template: partials/operating-areas.html:12:13: executing "partials/operating-areas.html" at <.areas>: can't evaluate field areas in type resource.Resource

Is it possible to load a data resource this way?


Display a list of items via data json file
#2

There’s likely a better way to write this, but I think this will work for you for now:

<ul>
{{ $resource := (.Resources.GetMatch "areas.json").RelPermalink }}
{{ $data := getJSON "content" $resource }}
{{ range $areas := $data }}
    {{ range $area := $areas }}
    <li>{{ $area }}</li>
    {{ end }}
{{ end }}
</ul>

#3

Thanks this worked.


#4

#5

Hi @bep
can you always unmarshal this?

From my old C++ view unmarshal should be under the surfarce as implementation detail.
Normal user will not understand it. The PROs could use a .Raw property to access the unmarshalled data.

I started this comment with my understanding of marshalling. Could be I’m wrong with this.


#6

In my head there are two fundamental different ways to do this (correct me if I’m wrong. You can either:

  1. Hide that “implementation detail” and create a more abstract API, aka. getJSON, getTOML, getCSV, getYAML etc.
  2. Assume your users are note idiots, and give them the freedom to do whatever: {{ resources.Get "my.json" | unmarshal }}

In my head, 2) is better for everyone.

So, the word unmarshal may be unfriendly/foreign for many, but it’s in so widespread use that I think we can use it: " unmarshalling or unmarshaling refers to the process of transforming a representation of an object that was used for storage or transmission to a representation of the object that is executable."

So, in Hugo term: We have a Resource which is a string, but need to have it in a format that we can range over in the templates, so we unmarshal it.

But instead of me writing these long epos everytime the “why do it this way?”, I suggest you complete that sentence and explain to me “why not?” and “what would you recommend as an alternative approach?”


#7

OK - was a question only

Why not - is this for 1. or 2. :wink:


#8

It is for your question in general. Why do you suggest that Unmarshal be hidden under the surface?


#9

-> Wiki
transforming the memory representation of an object to a data format suitable for storage or transmission

It was always hidden in API for RPC call (15 years ago). Old school :wink: .Net does it implicit if needed.

Do we need the unmarshalled data in Hugo?


#10

Certainly way more than you need, say, the JSON in text format. If you want to do something with JSON (or TOML etc.) and do not want to “hand parse” it (which is extremely unpractical, if at all possible, in Go templates), you need to unmarshal it.

If you want to quote Wikipedia, you need to copy and paste it, so no information gets lost. To me it looks like you mix marshal and unmarshal.


#11

I will not waste your time, IIRC:

marshal - from memory to storage or transmission
unmarshal - from storage or transmission to memory

No need for me to discuss it here more - was only a question


#12

+1 from me for this proposed way:

{{ resources.Get "my.json" | unmarshal }}