简体   繁体   中英

Jekyll / Liquid > Creating JSON > Substitute key value in hash output

Warning: I am not a coder and am almost sure I have misused terms.

Short:

When outputting an array, how to substitute a value for a specific key in the array with an alternate value from a key in a data file array?

Long

I will use simplified example for brevity.

I have and object in front matter with an array of key/values.

article:
  name: An article
  date: some date
  author: Tim

I output that array using the jsonify tag like so:

{{ page.article | jsonify }}

I also have a person data file like so:

Tim
  firstName: Tim
  surname: Bradley
  occupation: coffee consumer

Bob
  firstName: Robert
  surname: De Niro
  occupation: Taxi Driver

What I want to do is output the article array but substitute the value (Tim) for one key (author) with a value (say Bradley) from data file object.

I suppose the process might be something like: 1. go over array 2. locate author value 3. match value to corresponding data item 4. capture data item's replacement values 5. replace page array's key value with item's key value replacement 6. output amended array

I want to select the key value attribute ("author"=>"value"), not its value ("Tim"), because in practice the value ("Tim") is repeated several times in the object and I can't select the specific one - unless someone knows how to say select the first Tim after "author".

I don't wish to simply repeat the values of the array because I envisage adding and removing key values on a case by case (read page by page) basis.

How can I do this?

Can this even be done with liquid and jekyll?

Does this even make sense to anyone?

Thanks for any help in advance!

EDIT:

I am adding a few comments by way of an attempt at clarification. Once again, I warn that I am almost certainly mixing up my terminologies.

I have done some research, and what I am outputting is a hash as a json object.

Basically, I want is for the output to substitute the value of a particular key in the hash with a corresponding hash json generated from the data file.

After looking at the available filters and operators, I think the answer will lie in capturing the output of both hash sets, and then using replace filter to substitute the value for the corresponding data file with the key value in the original hash set.

If someone doesn't beat me to it, I will post an answer when I have it figured out - but I have other things on my plate at the moment.

This answer is hacky (not elegant), but it got the job done and in the absence of a cleaner solution having been provided I am posting this here.

The Issue: My goal was to output a hash in json format but substitute a specific value with values from a data file.

I was not able to find a way to manipulate the data prior to output. Instead, I took the process of capturing relevant strings output and then used the replace filter to substitute the values.

STEP ONE: CAPTURE VALUE TO BE REPLACED (OPTIONALLY KEY TOO)

I captured the value I wanted to replace in json format. I manually inserted the key in json format too, and in case there were other instances of the same string in values for other keys in the hash:

{% capture articleAuthorNameValue %}
"author":"{{ page.article.author }}"
{% endcapture %}

STEP TWO: CAPTURE THE SUBSTITUTE VALUES

Self Explanatory but again remember to use the jsonify filter because you are replacing values expressed in json format.

{% capture articleAuthorNameSubstituteValue %}
{{ site.data.person[page.article.author] | jsonify }}
{% endcapture %}

STEP THREE: OUTPUT & SUBSTITUTE

Output the values as json and replace captured values.

{{ page.article | jsonify | replace: articleAuthorNameValue, articleAuthorNameSubstituteValue }}

As I implied - Very Ugly but got the job done.

First, I'm not sure why your front matter is

---
article:
  name: An article
  date: some date
  author: Tim
---

and not

---
name: An article
date: some date
author: Tim
---

I'll go with the second form, because it needs shorter expression to get datas from it. eg : page.article.author vs page.author

Your data files is also not validating. A correct form is :

Tim:
  firstName: Tim
  surname: Bradley
  occupation: coffee consumer

Bob:
  firstName: Robert
  surname: De Niro
  occupation: Taxi Driver

Now when you want to access author's datas from post or page datas, you're not obliged to replace author key by authors datas. You can just extract authors datas from the key :

{% for post in site.posts %}
  <h1>{{ post.title }}</h1>

  # creating a new variable containing an author object
  {% assign author = site.data.authors[post.author] %}

  # if we have found an author
  {% if author %}
    <p>{{ author.firstName }} {{ author.surname }}</p>
  {% endif %}

{% endfor %}

You can do this with a custom Jekyll filter.

Drop this in /_plugins/ as replace_keys.rb

module Jekyll
  module ReplaceKeysFilter
    
    def replace_keys(input, *keys)
      begin
        keys = [] if keys.to_a.empty?
        if input.is_a?(Hash)
          return _replace_keys(input, keys)
        elsif input.is_a?(Jekyll::Drops::DocumentDrop)
          return _replace_keys(input.hash_for_json(), keys)
        else
          "Error: Unhandled class type #{input.class}"
        end
      rescue => e
        "Error: #{e}."
      end
    end

    private

    def _replace_keys(the_hash, keys)
      i = 0
      until i + 2 > keys.length
        k = keys[i]
        v = keys[i+1]
        the_hash[k] = v if the_hash.key?(k)
        i += 2
      end
      return the_hash
    end
    

  end
end

Liquid::Template.register_filter(Jekyll::ReplaceKeysFilter)

Then use the filter in your template to remove one or more keys from your object.

Example Usage

Replace the content of the post object.

<pre>{{ post | replace_keys: "content", "new content" | pretty_json }}</pre>

Replace the content and output of the post object.

<pre>{{ post | replace_keys: "content", "new content", "output", "new output" | pretty_json }}</pre>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM