Design

Store and transform

Store, modify, and transform JSON to simplify your templates
ENTERPRISE FEATURE Available for:
Carbone Cloud
Carbone On-premise
Embedded Carbone JS
  v5.0+ 

This feature is officially available in Carbone v5. However, you can activate it in v4 by inserting {o.preReleaseFeatureIn=4022011} into your template.
For more details, refer to the Files and features documentation.

Store values -> :set(absolutePath)

The :set(absolutePath) formatter allows you to store values in data. absolutePath specifies the destination where the value will be stored.

A Carbone tag using :set does not print anything in the generated report. The tag is removed when executed. A loop with iterators [i] cannot be used in combination with :set.

Example: store the sum in c.mySum

data
{
  "cars": [
    { "qty" : 1 },
    { "qty" : 4 }
  ]
}
template
{d.cars[].qty:aggSum:set(c.mySum)}Print stored value: {c.mySum}
Carbone Merge Icon
result
Print stored value: 5

Example with order of execution:

data
{
  "price" : 1
}
template
{d.price:add(10):set(d.total1)}
{d.total1:add(20):set(d.total2)}
Result: {d.total2}
Carbone Merge Icon
result
  Result: 31

Modify JSON -> :set(.relativePath)

Add or modify attributes in your data using a JSON relative path.

In this example, the Carbone tags {d.cars[].qty:append(' tyres'):set(.newInfo)} adds the attribute "newInfo" to all objects in the "cars" array.

data
{
  "cars": [
    { "qty" : 1 },
    { "qty" : 4 }
  ]
}
template
{d.cars[].qty:append(' tyres'):set(.newInfo)}JSON Modified{d:printJSON}JSON Usage{d.cars[i].newInfo}{d.cars[i+1].newInfo}
Carbone Merge Icon
result
JSON Modified{
  "cars": [
    {"qty": 1, "newInfo": "1 tyres"},
    {"qty": 4, "newInfo": "4 tyres"}
  ]
}JSON Usage1 tyres4 tyres

Transform JSON -> :set(absolutePath[])

Generate a completely new JSON structure with :set formatter.

Here is an overview of the syntax:

{ d.sourceArray[arrayFilter] :set( c.destinationArray[searchExpression] )}

Learn the basics with simple examples:

Advanced usage with search/join expressions:

Cloning arrays

{ d.myArray[] :set( c.new[] )}

Array of objects example:

data
{
  "myArray" : [
    { "country" : "A", "city" : "1A" },
    { "country" : "A", "city" : "2A" },
    { "country" : "B", "city" : "1B" }
  ]
}
template
{d.myArray[]:set(c.new[])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
JSON Generated{
  "new": [
    {"country": "A", "city": "1A"},
    {"country": "A", "city": "2A"},
    {"country": "B", "city": "1B"}
  ]
}

Array of string example:

data
{
  "myArray" : [ "A", "B", "C"]
}
template
{d.myArray[]:set(c.new[])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
JSON Generated{"new": ["A", "B", "C"]}

Selective array cloning

In this example, only the country attribute is injected into the new array.

As you can see, Carbone creates an array of string or an array of objects according to destination c.newArr1[] or c.newArr2[].country.

data
{
  "myArray" : [
    { "country" : "A", "city" : "1A" },
    { "country" : "A", "city" : "2A" },
    { "country" : "B", "city" : "1B" }
  ]
}
template
{d.myArray[].country:set(c.newArr1[])}{d.myArray[].country:set(c.newArr2[].country)}JSON Generated{c:printJSON}
Carbone Merge Icon
result
JSON Generated{
  "newArr1": ["A", "A", "B"],
  "newArr2": [
    {"country": "A"},
    {"country": "A"},
    {"country": "B"}
  ]
}

Merge arrays

data
{
  "myArray" : [
    { "country" : "A", "city" : "1A" },
    { "country" : "A", "city" : "2A" },
    { "country" : "B", "city" : "1B" }
  ],
  "myArray2" : [
    { "country" : "C", "city" : "1C" },
    { "country" : "A", "city" : "3A" }
  ]
}
template
{d.myArray[]:set(c.newArr[])}
{d.myArray2[]:set(c.newArr[])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
 JSON Generated{
  "newArr": [
    {"country": "A", "city": "1A"},
    {"country": "A", "city": "2A"},
    {"country": "B", "city": "1B"},
    {"country": "C", "city": "1C"},
    {"country": "A", "city": "3A"}
  ]
}

Distinct Merge

Carbone accepts a search expression enclosed in square brackets to determine how to add new items.

If an item in the new array matches the condition, the new item is merged with the existing one

{ d.myArray[] :set( c.new[ country = .country] )}

data
{
  "myArray" : [
    { "country" : "A", "city" : "1A" },
    { "country" : "A", "city" : "2A" },
    { "country" : "B", "city" : "1B" }
  ],
  "myArray2" : [
    { "country" : "C", "city" : "1C" },
    { "country" : "A", "city" : "3A" }
  ]
}
template
{d.myArray[]:set(c.new[country=.country])}
{d.myArray2[]:set(c.new[country=.country])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
 JSON Generated{
  "new": [
    {"country": "A", "city": "3A"},
    {"country": "B", "city": "1B"},
    {"country": "C", "city": "1C"}
  ]
}

Automatic creation of non-existing attributes

If the left operand of the condition does not exist, Carbone automatically creates it (c.new[].id).

data
{
  "myArray" : [
    { "country" : "A" },
    { "country" : "A" },
    { "country" : "B" }
  ],
  "myArray2" : [
    { "country" : "C" },
    { "country" : "A" }
  ]
}
template
{d.myArray[]:set(c.new[id=.country])}
{d.myArray2[]:set(c.new[id=.country])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
 JSON Generated{
  "new": [
    {"country": "A", "id": "A"},
    {"country": "B", "id": "B"},
    {"country": "C", "id": "C"}
  ]
}

Group data in nested arrays

Carbone accepts a search expression enclosed in square brackets to determine how to add new items.

If an item in the new array matches the condition, the new item is merged with the existing one

{ d.myArray[] :set( c.countries[ id = .country].cities[] )}

data
{
  "myArray" : [
    { "country" : "A", "city" : "1A" },
    { "country" : "A", "city" : "2A" },
    { "country" : "B", "city" : "1B" },
    { "country" : "B", "city" : "2B" },
    { "country" : "A", "city" : "3A" }
  ]
}
template
{d.myArray[]:set(c.countries[id=.country].cities[])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
JSON Generated{
  "countries": [
    {
      "id": "A",
      "cities": [
        {"country": "A", "city": "1A"},
        {"country": "A", "city": "2A"},
        {"country": "A", "city": "3A"}
      ]
    },
    {
      "id": "B",
      "cities": [
        {"country": "B", "city": "1B"},
        {"country": "B", "city": "2B"}
      ]
    }
  ]
}

Other examples

Here, only city is injected into the :set. Carbone creates an array of strings.

data
{
  "myArray" : [
    { "country" : "A", "city" : "1A" },
    { "country" : "A", "city" : "2A" },
    { "country" : "B", "city" : "1B" },
    { "country" : "B", "city" : "2B" },
    { "country" : "B", "city" : "3B" },
    { "country" : "A", "city" : "3A" }
  ]
}
template
{d.myArray[].city:set(c.countries[title=.country].cities[])}JSON Generated{c:printJSON}
Carbone Merge Icon
result
JSON Generated{
  "countries": [
    {
      "title": "A",
      "cities": ["1A", "2A", "3A"]
    },
    {
      "title": "B",
      "cities": ["1B", "2B", "3B"]
    }
  ]
}

Join two arrays -> :set(absolutePath[])

Here is a basic example to join two separate arrays:

data
{
  "actors": [
    { "id" : 10, "firstName" : "Keanu"  },
    { "id" : 20, "firstName" : "Margot" }
  ],
  "movies": [
    { "actorId" : 10, "name" : "Matrix"    },
    { "actorId" : 20, "name" : "Babylon"   },
    { "actorId" : 10, "name" : "John Wick" }
  ]
}
template
{d.actors[]:set(c.actors[id=.id])}
{d.movies[]:set(c.actors[id=.actorId].movies[])}JSON Generated{c.actors:printJSON}
Carbone Merge Icon
result
 JSON Generated[
  {
    "id": 10,
    "firstName": "Keanu",
    "movies": [
      {"actorId": 10, "name": "Matrix"},
      {"actorId": 10, "name": "John Wick"}
    ]
  },
  {
    "id": 20,
    "firstName": "Margot",
    "movies": [
      {"actorId": 20, "name": "Babylon"}
    ]
  }
]