0

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);
}
lorenz
  • 4,538
  • 1
  • 27
  • 45
Urs
  • 4,984
  • 7
  • 54
  • 116

4 Answers4

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>
lorenz
  • 4,538
  • 1
  • 27
  • 45
  • Lol, I just was writing... this ;) just to notice - for transient field skip the DB field and TCA declaration. – biesior Dec 03 '14 at 17:55
  • Haha :-). I clarified my answer with "DB field and". Thanks. – lorenz Dec 03 '14 at 18:00
  • 1
    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. – Urs Dec 03 '14 at 21:06
  • And the vhs viewhelper `v:format.json.decode()` mentionned by Jost does the job as well – Urs Dec 03 '14 at 21:09
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

biesior
  • 55,576
  • 10
  • 125
  • 182
  • 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". – Urs Dec 03 '14 at 14:55
  • else I'll just parse the string earlier, but I thought it would be nice to do it that way :-) – Urs Dec 03 '14 at 14:57
  • 1
    I think (have not tried) you can do that with ViewHelpers from EXT:vhs. ``. EXT:vhs rulez. – Jost Dec 03 '14 at 15:32
  • @Urs lorenz gave a sample of transient field, so I won't duplicate it, as actually this is the solution you are looking for ;) – biesior Dec 03 '14 at 17:57
  • @Jost this works too, thanks a lot as well! @ biesior - so it's not strictly fluid, but very close. – Urs Dec 03 '14 at 21:08
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).

Claus Due
  • 4,166
  • 11
  • 23
  • wohooo - that sounds nice! probably the performance with the transient field is faster, right? – Urs Sep 03 '16 at 06:35
  • 1
    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. – Claus Due Sep 03 '16 at 12:57
0
<script type="text/javascript">
  var json = '{f:format.htmlentitiesDecode(value:your_value)}';
  var your_value = jQuery.parseJSON(json);
</script>
  • 3
    Welcome to stack overflow :-) Please look at [answer]. You should provide some information why your code solves the problem. Code-only answers aren't useful for the community. – JimHawkins Feb 09 '17 at 09:23