Array of arrays compressed into a single array

Enonic version: 7.10.3
OS: Mac 13.5

Hi!

This could perhaps be categorised under the “Help” category, but it does seem like a bug so I’m categorising it as such :slight_smile:

The context
We are creating and showing content based on an external API. At the moment some data is stored in Content Studio and other data is retrieved from the API when the content is first rendered. This is inefficient and we would like to store the retrieved data on the content, which leads us to the issue.

The issue
From the API we receive an object where some data is an array containing two arrays, as shown in the image below.

Data from API

When the data is stored on the content in Content Studio this array of arrays is compressed into a single array, again, shown below.

Data after storage in CS

I am aware that single element arrays are removed and only the data inside the array is stored, e.g. {"data": ["a string"]}{"data": "a string"} as explained in this bug report from XP6. It is somewhat unclear if the answer to that bug report only applies to single element arrays or also applies to my case. I assume the same underlying Java API is used in XP7, is this correct? And is the behaviour I’m experiencing a result of how the API works?

Thanks!

In order to store this kind of data on a content you’d have to build a content type schema that reflects your provided data structure. There’s no concept of “classic” array of arrays (as explained in the topic you linked to) but you can use PropertySet to achieve something very similar.

Here’s a content type which would store underlying data as an array of PropertySets (“level-1”) each of which is an array of strings:

  <form>
    <item-set name="level-1">
    <occurrences minimum="0" maximum="0"/>
    <label>Level 1</label>
      <items>
        <input name="level-2" type="TextLine">
          <label>Level 2</label>
          <occurrences minimum="0" maximum="0"/>
        </input>
      </items>
    </item-set>
  </form>

Values from input type “TextLine” (strings):

image

Note that empty values are stored as “null”, not as an empty string.

And here’s the same content type which does exactly the same for numbers:

  <form>
    <item-set name="level-1">
    <occurrences minimum="0" maximum="0"/>
    <label>Level 1</label>
      <items>
        <input name="level-2" type="Long">
          <label>Level 2</label>
          <occurrences minimum="0" maximum="0"/>
        </input>
      </items>
    </item-set>
  </form>

Values from input type “Long” (numbers):

image

Hi Fredrik,

I’ve written a lot of XP-code where I store data in XP to make it searchable and fast, and serve it out on the page.

I don’t think it’s a good idea to import data directly as content that is editable from Content Studio. (It always ends up being a fight about what is the source-of-truth between the API and the edited content).

Instead use a separate XP-repo to store the data (not viewable from content studio), and use a custom selector to tie it to content in XP.

My recommended approach is as follows:

  1. Use repo-lib to create a local repository (in elastic search) to store the data (in main.js I check if it exists, and if not I create it).
  2. Use scheduler-lib to schedule a task that:
    • Uses http-client-lib to import the data from your API
    • Store it in the repo I created earlier using node-lib.
    • Repeatadly check and update the repo with data from the API (maybe every night)
  3. I create a custom-selector that exposes entries in my repo
  4. I use that custom-selector in my content type where I want to create a relation to the data from the API.

– Tom Arild

5 Likes

Great answer, @tom :clap: