Home > Software design >  Jsonnet object comprehension in array
Jsonnet object comprehension in array

Time:02-17

I know how to do Array comprehension in Jsonnet like this, with the for loop the one object in the array gets looped with all my defined values:

local values = [
  'foo',
  'bar',
  'foobar',
];
{
list: 'movies', 
items: [
  {
      title: 'title',
      language: 'english',
      metadata: {
        author: 'god',
        value: v,
      },
    },
    for v in values
  ],
}

output:

{
   "items": [
      {
         "language": "english",
         "metadata": {
            "author": "god",
            "value": "foo"
         },
         "title": "title"
      },
      {
         "language": "english",
         "metadata": {
            "author": "god",
            "value": "bar"
         },
         "title": "title"
      },
      {
         "language": "english",
         "metadata": {
            "author": "god",
            "value": "foobar"
         },
         "title": "title"
      }
   ],
   "list": "movies"
}

I now want to do this with multiple objects in an array like this:

local values = [
  'foor',
  'bar',
  'foorbar',
];
{
list: 'movies', 
items: [
  {
      title: 'title',
      language: 'english',
      metadata: {
        author: 'god',
        value: v,
      },
    },
    {
      title: 'title2',
      language: 'german',
      metadata: {
        author: 'devil',
        value: v,
      },
    },
    {
      title: 'title3',
      language: 'spanish',
      metadata: {
        author: 'chutulu',
        value: v,
      },
    },
  ],
}

What to I need to do to have the following output? So every of the three objects get the three values

{
   "items": [
      {
         "language": "english",
         "metadata": {
            "author": "god",
            "value": "foor"
         },
         "title": "title1"
      },
      {
         "language": "english",
         "metadata": {
            "author": "god",
            "value": "bar"
         },
         "title": "title1"
      },
      {
         "language": "english",
         "metadata": {
            "author": "god",
            "value": "foorbar"
         },
         "title": "title1"
      }
      {
         "language": "german",
         "metadata": {
            "author": "devil",
            "value": "foor"
         },
         "title": "title2"
      },
      {
         "language": "german",
         "metadata": {
            "author": "devil",
            "value": "bar"
         },
         "title": "title2"
      },
      {
         "language": "german",
         "metadata": {
            "author": "devil",
            "value": "foorbar"
         },
         "title": "title2"
      }
      {
         "language": "spanish",
         "metadata": {
            "author": "chutulu",
            "value": "foor"
         },
         "title": "title3"
      },
      {
         "language": "spanish",
         "metadata": {
            "author": "chutulu",
            "value": "bar"
         },
         "title": "title3"
      },
      {
         "language": "spanish",
         "metadata": {
            "author": "chutulu",
            "value": "foorbar"
         },
         "title": "title3"
      }
   ],
   "list": "movies"
}

CodePudding user response:

Pasting below two possible solutions, with their own tradeoffs (depending on how further you need to customize the final items array):

1) Mixing arrays, with value "placement" in the comprehension

local values = [
  'foor',
  'bar',
  'foorbar',
];
local movies = [
  {
    title: 'title',
    language: 'english',
    metadata: {
      author: 'god',
    },
  },
  {
    title: 'title2',
    language: 'german',
    metadata: {
      author: 'devil',
    },
  },
  {
    title: 'title3',
    language: 'spanish',
    metadata: {
      author: 'chutulu',
    },
  },
];

// Combine the `values` and `movies` arrays into `items`,
// overloading movie's metadata.value with each value,
// note the `metadata :` syntax.
{
  list: 'movies',
  items: [
    movie { metadata : { value: value } }
    for movie in movies
    for value in values
  ],
}

2) Create movies(v) function that outputs the 3-lang array, aggregate over values and flatten it

local values = [
  'foor',
  'bar',
  'foorbar',
];
local movies(v) = [
  {
    title: 'title',
    language: 'english',
    metadata: {
      author: 'god',
      value: v,
    },
  },
  {
    title: 'title2',
    language: 'german',
    metadata: {
      author: 'devil',
      value: v,
    },
  },
  {
    title: 'title3',
    language: 'spanish',
    metadata: {
      author: 'chutulu',
      value: v,
    },
  },
];

// To build the final `items` array we need to flatten
// the array-of-arrays created by the comprehension, as
// each element is indeed a 3-movies array
{
  list: 'movies',
  items: std.flattenArrays([
    movies(v)
    for v in values
  ]),
}
  • Related