Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
require 'json'
require 'net/http'
# JSON parser tag, creating map for use in jekyll markdown
# Alex.Heneveld @ Cloudsoft Corp (remove spaces and add the .com)
# Released under APL 2.0
# usage: {% jsonball varname from TYPE PARAM %}
#
# where TYPE is one of {data,var,file,page}, described below
# drop this into your _plugins/ folder, then you can write, e.g.
#
# {% jsonball foo from data { "a": "b" } %}
#
# and then later refer to {{ foo.a }} to get b inserted
# more usefully, you can load it from a variable x, e.g.
# {% capture x %}{% include toc.json %}{% endcapture %}
#
# {% jsonball foo from var x %}
# even better, to read from a file, say toc.json
# (absolute, or relative to the page being jekylled):
#
# {% jsonball foo from file toc.json %}
#
# then e.g. {% for record in jsonball %} {{ record.name }} {% endfor %}
# to print out all the name entries (or build a fancy TOC sidebar)
# or even better yet, to read from a URL
#
# {% jsonball feed from url http://www.foo.com/bar.json %}
#
# then e.g. {% for record in feed %} {{ record.key }} {% endfor %}
# and finally, if that json file might itself contain liquid tags,
# or need jekylling, treat it as a page and it will get jekylled
# (we use this for toc.json reading from subdirs' toc.json files):
#
# {% jsonball foo from page toc.json %}
module JekyllJsonball
class JsonballTag < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
def render(context)
if /(.+) from var (.+)/.match(@text)
context[$1] = JSON context[$2]
return ''
end
if /(.+) from data (.+)/.match(@text)
context[$1] = JSON $2
return ''
end
if /(.+) from file (.+)/.match(@text)
context[$1] = JSON page_relative_file_contents(context, $2.strip)
return ''
end
if /(.+) from page (.+)/.match(@text)
context[$1] = JSON jekylled_page_relative_file_contents(context, $2.strip)
return ''
end
if /(.+) from url (.+)/.match(@text)
base_url = $2
resp = Net::HTTP.get_response(URI.parse(base_url))
data = resp.body
context[$1] = JSON data
return ''
end
# syntax error
return 'ERROR:bad_jsonball_syntax'
end
def page_relative_file_contents(context, filename)
jekyllSite = context.registers[:site]
dir = jekyllSite.source+'/'+File.dirname(context['page']['url'])
if !filename.match(/\/.*/)
filename = dir + '/' + filename
end
file = File.open(filename, "rb")
return file.read
end
def jekylled_page_relative_file_contents(context, filename)
jekyllSite = context.registers[:site]
targetPage = Jekyll::Page.new(jekyllSite, jekyllSite.source, File.dirname(context['page']['url']), filename)
targetPage.render(jekyllSite.layouts, jekyllSite.site_payload)
targetPage.output
end
end
end
Liquid::Template.register_tag('jsonball', JekyllJsonball::JsonballTag)
@equivalentideas

This comment has been minimized.

Copy link

equivalentideas commented Nov 10, 2014

Thanks for this @StevenBlack . Is there a way to combine the variable option with the url option, to use a url in a variable?

When I run:

          {% if text.openlibrary.id %}
            {% assign text_data_url = text.openlibrary.id | prepend: 'https://openlibrary.org/books/' | append: '.json' %}

            {% if text_data_url %}
              {% jsonball text_data from url text_data_url %}
              {{ text_data }}
            {% endif %}
          {% endif %}

I get Liquid Exception: no implicit conversion of nil into String in library.html.

And:

{% if text.openlibrary.id %}
            {% assign text_data_url = text.openlibrary.id | prepend: 'https://openlibrary.org/books/' | append: '.json' %}

            {% if text_data_url %}
              {% jsonball text_data from var text_data_url %}
              {{ text_data }}
            {% endif %}
          {% endif %}

gives me Liquid Exception: 757: unexpected token at 'https://openlibrary.org/books/OL25047097M.json' in library.html. If I write the url straight in instead of the variable it works perfectly, but I need it to be dynamic. Thanks for the useful plugin and your help :)

@combs

This comment has been minimized.

Copy link

combs commented May 24, 2017

@equivalentideas 2.5 years later... I was able to get this working by changing line 69 to:

    		base_url = context[$2]

and passing in the name of the variable:

	{% jsonball feed from url theurl %}

(where theurl is my variable)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.