Parse an existing JSON string in fluid template?
Asked Answered
T

4

1

I have a JSON string with some data I want to render in a template. As Fluid arrays are notated in JSON too, I thought I might just take that JSON string and hand it over to fluid, telling it to treat it just like some other array and use it in the template.

Thus gaining a lot of speed and losing overhead (don't have to split the JSON data up to save it in the DB, can template it easily in fluid).

It wouldn't work, at least not how I tried it.

<f:alias map="{item.jsonData}">
  {fieldname}
</f:alias>

It - of course - complained it had received a string, not an array.

Do I have to build a viewhelper and do json_decode before returning the array to fluid? Or is there a more native way?

Here's the basic controller action:

/**
 * action show
 *
 * @param \NAMESPACE\Myext\Domain\Model\Item $item
 * @return void
 */
public function showAction(\NAMESPACE\Myext\Domain\Model\Item $item) {
    $this->view->assign('item', $item);
}
Tomtoma answered 3/12, 2014 at 14:42 Comment(0)
H
5

As an alternative to using a custom ViewHelper, you could use a transient property in your model. Let's assume your model has a property "jsonData" that is a JSON encoded string.

Now, you add another property $jsonArray and a getter for it:

/**
 * @var array
 * @transient
 */
protected $jsonArray;

And in the getter, you decode the data:

/**
 * @return array
 */
public function getJsonArray() {
  return json_decode($this->jsonData);
}

A transient property is like a virtual property. You don't need a DB field and TCA definition for it and you cannot do queries based on it, but you have the data available in your object:

<f:for each="{item.jsonArray}" as="value">
 {value}
</f:for>
Handknit answered 3/12, 2014 at 17:52 Comment(4)
Lol, I just was writing... this ;) just to notice - for transient field skip the DB field and TCA declaration.Mutiny
Haha :-). I clarified my answer with "DB field and". Thanks.Handknit
Guys, this is awesome! Thank you so much! (I first thought it would work just by json_decoding directly in the getter for jsonData, but that won't work due to different data type string/array). The transient property is great! Very elegant.Tomtoma
And the vhs viewhelper v:format.json.decode() mentionned by Jost does the job as wellTomtoma
M
1

Yes you need to use own viewhelper or decode your JSON string in the controller (I prefer the last), depends which is more comfortable for you.

There is no way to decode JSON in Fluid, sorry

Mutiny answered 3/12, 2014 at 14:48 Comment(5)
I'd rather do it in the controller too. Can you give me a little nudge? I've posted the (standard) controller action above. Before assigning the $item to the view, I would like to decode $item.jsonData so it becomes "fluidable".Tomtoma
else I'll just parse the string earlier, but I thought it would be nice to do it that way :-)Tomtoma
I think (have not tried) you can do that with ViewHelpers from EXT:vhs. <v:variable.set name="decodedJson" value="{insertYourJsonStringHere -> v:format.json.decode()}"/>. EXT:vhs rulez.Lareelareena
@Tomtoma lorenz gave a sample of transient field, so I won't duplicate it, as actually this is the solution you are looking for ;)Mutiny
@Lareelareena this works too, thanks a lot as well! @ biesior - so it's not strictly fluid, but very close.Tomtoma
K
1

In Fluid standalone and TYPO3v8 and up:

$this->view->assign('json', new \TYPO3Fluid\Fluid\Variables\JSONVariableProvider('path/to/my/fileOrUrl.json'));
// then in Fluid:
{json.any.path.inside.jsonfile}

See also the ChainedVariableProvider which will allow you to use for example a JSON file as base variables and variables from another array to overlay those. Using this VariableProvider causes Fluid to look for a (non-NULL) variable in the normal array first, then the JSON file (or vice versa if you order it thusly).

Kutaisi answered 3/9, 2016 at 0:53 Comment(2)
wohooo - that sounds nice! probably the performance with the transient field is faster, right?Tomtoma
Approximately the same performance, main difference is an object reference gets transferred instead of an array. You'd need a REALLY big JSON array (not object) to notice any difference in performance. Benefit is the API and combination with other variable providers.Kutaisi
V
0
<script type="text/javascript">
  var json = '{f:format.htmlentitiesDecode(value:your_value)}';
  var your_value = jQuery.parseJSON(json);
</script>
Vehemence answered 9/2, 2017 at 8:16 Comment(1)
Welcome to stack overflow :-) Please look at How to Answer. You should provide some information why your code solves the problem. Code-only answers aren't useful for the community.Attending

© 2022 - 2024 — McMap. All rights reserved.