How to conditionally check JSON data?

Hiya folks. Please give me pointers on structuring my template to check if a value exists after using getJSON. (I don’t have a git repo available, nor a public fossil repo available, but this is all a single template, so I’ll try to explain without a working sample…)

I’m building a vendor list, pulling data from Wikidata. My vendor files have two front matter values, here’s one for Mailgun and Linode, the only two I’ve made at this point:

---
title: "Mailgun"
wikidataid: "Q105539224"
---
---
title: "Linode"
wikidataid: "Q6554704"
---

I’d like to list them on the same page, with some basic info. The JSON created by the API I’m accessing is pretty wild, here’s an example for Mailgun, where I only return the results in English: https://www.wikidata.org/w/api.php?action=wbgetentities&ids=Q105539224&languages=en&format=json

Okay, so here’s my layouts/vendors/list.html:

{{ define "main"  }}
<header>
    <h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
{{- range .Pages | shuffle -}}
<hr />
<article>
    {{ $wikidataid := .Params.wikidataid -}}
    {{- $wikidata := getJSON "https://www.wikidata.org/w/api.php?action=wbgetentities&ids=" $wikidataid "&languages=en&format=json" -}}
    {{- $data := index $wikidata "entities" $wikidataid -}}
    {{- $claim := index $wikidata "entities" $wikidataid "claims" -}}
    {{- $website := index $claim "P856" 0 "mainsnak" "datavalue" "value" -}}
    {{- $status := index $claim "P9138" 0 "mainsnak" "datavalue" "value" -}}
    <h2>{{ .Title }} {{ with index $data "descriptions" "en" "value" }}({{ . }}){{- end -}}</h2>
    {{ with $website -}}<p>Website: {{ . | markdownify }}</p>{{- end }}
    {{ with $status -}}<p>Status website: {{ . | markdownify }}</p>{{- end }}   
</article>
{{ end -}}
{{- end -}}

When I have just Mailgun listed it renders fine, as both those properties (website and status website) are present:

<article>
    <h2>Mailgun (API-based email delivery service)</h2>
    <p>Website: <a href="https://mailgun.com">https://mailgun.com</a></p>
    <p>Status website: <a href="https://status.mailgun.com">https://status.mailgun.com</a></p>   
</article>

However, when I try Linode, I get an error:

Rebuild failed:

Failed to render pages: render of “section” failed: “/home/maiki/projects/websites/maiki.xyz/layouts/vendors/list.html:14:19”: execute of template failed: template: vendors/list.html:14:19: executing “main” at <index $claim “P9138” 0 “mainsnak” “datavalue” “value”>: error calling index: index of nil pointer

I’ve been very lucky so far, all the JSON I’ve imported had all the values I expected. I thought the with would cover it, but I’m stumped with checking if it exists of not before assigning it…

How should I proceed? :slight_smile:

It fails at index function, is not even hitting the with part.

I think you can range the key path and check the return of every step of index function.

layouts/partials/index-loop.html

{{- $value := .map -}}
{{- range $key := .path -}}
  {{- if $value -}}
    {{- $value = index $value $key -}}
  {{- end -}}
{{- end -}}

{{- return $value -}}

This Layout:

{{ define "main"  }}
<header>
    <h1>{{- .Title -}}</h1>
</header>
{{ .Content }}
{{- range .Pages | shuffle -}}
<hr />
<article>
    {{ $wikidataid := .Params.wikidataid -}}
    {{- $wikidata := getJSON "https://www.wikidata.org/w/api.php?action=wbgetentities&ids=" $wikidataid "&languages=en&format=json" -}}
    {{- $data := index $wikidata "entities" $wikidataid -}}
    {{- $claim := index $wikidata "entities" $wikidataid "claims" -}}
++                                                                               
    {{- $website := partial "index-loop.html" (dict 
           "map" $claim 
           "path" (slice "P856" 0 "mainsnak" "datavalue" "value")
    ) -}}
    {{- $status := partial "index-loop.html" (dict 
           "map" $claim 
           "path" (slice "P9138" 0 "mainsnak" "datavalue" "value") 
    ) -}}
++                                                                               
    <h2>{{ .Title }} {{ with index $data "descriptions" "en" "value" }}({{ . }}){{- end -}}</h2>
    {{ with $website -}}<p>Website: {{ . | markdownify }}</p>{{- end }}
    {{ with $status -}}<p>Status website: {{ . | markdownify }}</p>{{- end }}   
</article>
{{ end -}}
{{- end -}}
2 Likes

Yep, and I thought maybe there was a way to work index so I could just call all the claims (those are the P values on Wikidata, such as “P9138”) as needed…

@pamubay you comprehensive answer is appreciated, and made me realize I didn’t want to type that much! :slight_smile:

I ended up getting away with:

{{ with $claim.P9138 -}}<p>Status website:{{ index $claim "P9138" 0 "mainsnak" "datavalue" "value" | markdownify }}</p>{{- end }}

My plan is to create a partial for each claim (since each with have their own paths to their values), and then reuse them as needed in my templates where I need them, something like:

{{ partial "claim/P9138.html" . }}
2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.