Closed reggi closed 6 years ago
you can easily do this using a custom liquid drop that wraps json files
@fw42 Hmm, just realized this is the repo for all of liquid not shopify's implementation on http://shopify.com right? Ugh... I gotta find a better place for this request.
so just so I understand what you want... You want to store a json file within your shopify theme editor, and then be able to use the parsed data within other Liquid templates in some easy way?
I want to create a liquid variable that is an object that has the contents of the parsed data. Yeah, I think you got it.
I use this in my own projects (with a custom parse_json
filter and a custom json
tag), and it's very useful, even when the data is inlined. For example:
{% json states %} {
"AL": "Alabama",
"AK": "Alaska",
"AZ": "Arizona"
} {% endjson %}
<select>
{% for state in states %}
<option value="{{ state[0] }}">{{ state[1] }}</option>
{% endfor %}
</select>
Or from some external source (json_string
here):
{% assign data = json_string | parse_json %}
...
Since I control the Liquid code in the projects where I use this, I haven't considered all of the security implications, but the only one I can think of off the top of my head would be parsing a maliciously-large JSON string.
I've never heard that idea before, so I would guess that there is not that much demand for it at Shopify, but then, the idea doesn't sound too crazy to me. @Shopify/liquid, thoughts?
Many people actually complain that it's not possible to "create objects" in Liquid. This would at least somehow satisfy that demand in a very generic way.
@carolineschnapp, @boourns, what do you think about this?
I can say that the ability to create and modify objects is huge in the way I often use Liquid. A few of my projects have filters for creating arrays and hashes and populating them (e.g., push
, put
, shift
, etc.).
This can open up systems to modification of data structures that have so far been immutable through Liquid and thus safe to expose to Liquid code. For example, if a CMS has a pages
array, and a push
filter is exposed, the array could contain the wrong data when it is used later, either inside Liquid or elsewhere in the system. But, such filters could be made to operate only on objects tagged (or wrapped) with an indication that they are explicitly Liquid-mutable.
All that being said, if the security and data integrity implications are well considered, this could be a big way to make Liquid usable for a wider range of applications.
Just my two cents. :)
We can't create arrays now, unless using the split filter:
{% assign my_array = 'Banana,Apple,Organic carrot' | split: ',' %}
Whatever we add here, we ought to be able to create arrays too.
In Shopify's Liquid, we can turn Liquid objects - some at least - to JSON, which has been extremely useful, example:
var product = {{ product | json }};
The other way around would be nice, I guess. I have not met with anyone requesting this before.
stealing nicks example, you could potentially do something like
{% json my_array %}
[ "banana", "apple", "organic carrot" ]
{% endjson %}
This is impossible in anything but the trivial case.
For example, in javascript I could do an AJAX GET from a server, and then try to convert it to a liquid object.
{% json my_array %}
$.get("server.json")
{% endjson %}
Since the JSON is calculated client-time, and liquid is server-side (and cached after the fact), this won't work.
@boourns: I think the original post was about storing fixed json things in a theme asset or stuff like that
Right, but we need to be careful to make sure that we're not creating impossible expectations.
@boourns nope, I have very possible expectations @fw42 nailed it, my idea is storing fixed json and having it accessible by the server via liquid variables. :cake: Not that hybrid ajax request thing you created @boourns
perhaps assign could simply learn how to deal with json data by detecting a { as first character?
On Wed, Aug 27, 2014 at 4:11 PM, Thomas Reggi notifications@github.com wrote:
@boourns https://github.com/boourns nope, I very possible expectations @fw42 https://github.com/fw42 nailed it, my idea is storing fixed json and having it accessible by the server via liquid variables. [image: :cake:]
— Reply to this email directly or view it on GitHub https://github.com/Shopify/liquid/issues/432#issuecomment-53633198.
+1
Will this be possible? (I mean in the shopify.com implementation) I actually really need to parse JSON strings as I have a specially tailored blog post editor which saves JSON as blog post content and I need to render the result in the templates.
I'd be storing HTML as usual but I really want the freedom to change the rendering independently on the database.
I need something like this:
<article>
{% assign elements = article.content | parse_json %}
{% for element in elements %}
<div class="{{ element.class }}">
{% case element.class %}
{% when 'img' %}
<img src="{{ element.data.url }}">
…
{% endcase %}
</div>
{% endfor %}
why don't you just change the Article#content method to do the json parsing for you? why does this need to happen in Liquid-land?
@fw42 Can I do that from a Shopify theme?
no
sorry I just saw your edit.. didn't get that you are talking about shopify..
What would you recommend for my case? I am pretty much left with rendering the article content on the client via JS which kind of sucks because of search engines and similar.
Would you consider implementing this on your side in some form?
I will bring this up for discussion internally and let you know.
@jankuca's use case case is a pretty good one too! @fw42 I'd love to hear what the internal chatter is :)
I'm totally at a loss, I started using en.defaults.json
in a very unconventional way, noticed today that you're not allowing arrays, integers, and bools. It's messing up my build process. Can we please, please, please get a json_parse
filter stat??
@reggi
en.default.json in the /locales folder? That's parsed by the Language page, for translation. You can't use that in an unconventional manner.
Hey @carolineschnapp!
I'm generating liquid files via ejs template with node.js all built around hacking the en.defaults.json
file, so I can use it as one big data-store / CMS.
en.defaults.json
You can see in that template file that I'm pulling in data from en.defaults using that t
filter. That whole template generates a liquid file that contains all the variables I need to pass it into a view component. Then I just need to call the id
, controller, and view and it renders the HTML with all the variables.
Next step would be taking deprecating that en.defaults.json
file out into smaller json files, and building liquid files with the data directly in it rather then pulling from en.defaults.json
. Since there's kind of no reason to even use it anymore (I didn't start out generating liquid with node).
I'd still love json_parse
:)
Since settings.html
does not allow Javascript, without json_parse
I am required to use CSV if I want an array of values. I really prefer JSON over CSV.
Please add json_parse
.
I was able to achieve this functionality by creating parse_json filter and then assign this result to variable in the template. Then you can simple access data as it should be an object. Here is the commit I made to locomotive_cms liquid extension. https://github.com/robinbortlik/liquid_extensions/commit/2b7a67281b55f25045ec4c44813ddd7535b00b3d
{% for event in contents.events %}
{% assign json = event.content | as_json %}
{% for ticket in json.tickets %}
{{ ticket.end_date }}
{% endfor %}
{% endfor %}
Great, hopefully Shopify will add it soon.
I would like this. For Shopify, tons of useful Variant-related yet non-price affecting data could be stored and used to manipulate the front-end, then tie in with Line Item Properties... :sweet_potato:
Any news on this? I would love to store json data in shopify metafields and then be able to parse it as liquid server side. I can think of lots of awesome applications.
What @horsejockey said!
I would love to store json data in [insert liquid-served tools'] metafields and then be able to parse it as liquid server side.
Very helpful, need it!
I would also really like this. At the moment I am building and parsing a custom string array with unusual chars as delimiters.. Json would be so much nicer!
Yes, please! This would be a great solution for all sorts of various problems.
The problem is that people will always use your system in unintended ways. In my case, I'm a software engineer being forced to use Jekyll - and from my perspective there are many things missing. Being able to create an array or hash in liquid directly seems like a no-brainer, as well as the ability to parse between types without requiring individual plugins. Just my 0.02.
Two things I think could be added:
json_parse
as mentioned by everyone else, doesn't seem difficult based on @robinbortlik's example{% assign names = ['Steve', 'Bill', 'Larry'] %}
Or:
{% assign person = {'name': 'Steve', age: 60} %}
Hash keys could be expressions that result in a string or int, and hash values and array items could be expressions resulting in any value. The Liquid strict parser could handle this pretty easily.
@kainjow ideally with json_parse
the you'd get what your talking about and the following would work.
{% assign array = '["Steve", "Bill", "Larry"]' | json_parse %}
{{ array[0] }} // Steve
{% assign object = '{"name": "Steve", "age": 60}' | json_parse %}
{{ object.name }} // Steve
@fw42 Any idea if we'll ever get a json_parse
filter?
The main idea is the filter json
is like javascript's JSON.stringify
, and json_parse
would be like JSON.parse
. Seems like a simple idea that would allow people to simple create arrays
and objects
in liquid.
@reggi yes, json can do it, but you're limited to hard coded strings. What if you want to use a variable exposed to Liquid already? Built-in support for the syntax would be far more powerful.
@kainjow totally, It's not fun but there are ways... 😬
{% assign jsonString = "" %}
{% assign jsonString = jsonString | append: "[" %}
{% for tag in product.tags %}
{% assign jsonString = jsonString | append: '"' %}
{% assign jsonString = jsonString | append: tag %}
{% assign jsonString = jsonString | append: '"' %}
{% if forloop.last == true %}
{% else %}
{% assign jsonString = append: "," %}
{% endif %}
{% endfor %}
{% assign jsonString = jsonString | append: "]" %}
{% assign yayJson = jsonString | json_parse %}
And building an object like this would be much worse.
I feel like the real reason we can't make objects / arrays is it would put too much on Shopify servers, and the rendering engine. 😢 So I doubt we'd ever get it via json_parse
or a native way of doing it.
function liquidToJSON(liquidString) {
return JSON.parse(liquidString.replace(/=>/g, ': ').replace(/(\s)nil(\s|,)/g, '"nil",').replace(/Liquid::ImageDrop/g, '"Liquid::ImageDrop"').replace(/\}(|\s+){/g, '},{'));
}
function JSONtoLiquid(json) {
return JSON.stringify(json).replace(/\"(|\s+):(|\s+)/g, '"=>').replace(/"nil",/g, 'nil').replace(/"Liquid::ImageDrop"/g, 'Liquid::ImageDrop').replace(/\},(|\s+){/g, '}{');
}
For anyone else tired of waiting for this
I'm also coming at this from a Shopify theme developer perspective, but I think a way to build up liquid objects through something like json_parse
would be great for mocking objects. For example, this could be used for mocking up Shopify objects for section on-boarding.
{% if onboarding %}
Create a mock article object
{% json article %}
{
"title": {{ 'onboarding.article-excerpt.title' | t | json }},
"content": {{ 'onboarding.article-excerpt.content' | t | json }}
}
{% endjson %}
{% endif %}
<div class="article-excerpt">
<h1 class="article-excerpt-title">{{ article.title }}</h1>
<div class="article-excerpt-content">{{ article.content }}</div>
</div>
Here's a longer example: https://gist.github.com/jnorth/2202368d02e9425d54e9e0bb3ee66887
Solution for this in Pull Request #867 we have been using the liquid side JSON parsing but we have hit slow downs on our site which everyone knows means lost sales so we are proposing the attached to bring json parsing into the standard filter functions.
Would love this feature. I'm currently trying to set a metafield value as a JSON object. This would be helpful when I'm using js to create a metafield using the API then easily access key/values of that object in Liquid.
I realize I can create a bunch of different metafields with different keys and values but this would help make my requests and code more concise.
Hi guys, what an interesting read I just had. Any news on the json_parser ?
I have a customer who is importing a lot of data via Airtable API from different tables and storing the file via Asset API inside the theme, but then there is no way to translate that file into shopify variables.
I had to read the file via javascript using getJSON and then doing everything else in Javascript Land. It would be very nice to have a Liquid Option.
Regards, Rafael
Another half-year and no update here. I certainly need this feature. Any update?
This filter would make a world of difference to so many developers, myself included.
This issue was a short novel, but I think we can all agree there are an incredible amount of use cases relating to both development and design where the json_parse filter would be useful. JSON has become increasingly more so the 'go-to' standard since the beginning of this issue as cited in the numerous relationships between design and JSON data structures.
Regards, {{ "{ name: 'Calvin' }" | json_parse }}
:)
I'd really love a
json_parse
filter. The below code does not work to convert a json file to a server-side liquid object. It is however, very possible to convert a json file to a javascript variable, but it's sadly not server-side, and bad for SEO to have content rendered by the client. I was going to attempt to break down the string using liquid itself but It's pretty hard. I've created objects with liquid in the past but they're quite crude you can check that out here, the tweet, the gist example.This is so simple for you guys to implement into production and it's a no brainer.
I just tried to use the new theming internationalization feature, I couldn't get it to work.
Ideally this type of thing could just be done with locales. But it would still be nice to have a
json_parse
.