{
  "schema_version": 2,
  "id": "integrate/redis-data-integration/data-pipelines/transform-examples/map-example",
  "title": "Restructure JSON or hash objects",
  "url": "https://redis.io/docs/latest/integrate/redis-data-integration/1.19.1/data-pipelines/transform-examples/map-example/",
  "summary": "",
  "content": "\nBy default, RDI adds fields to\n[hash](https://redis.io/docs/latest/develop/data-types/hashes) or\n[JSON](https://redis.io/docs/latest/develop/data-types/json) objects in the target\ndatabase that closely match the columns of the source table.\nIf you just want to limit the set fields in the output and/or rename some of them, you can use the\n[`output mapping`](https://redis.io/docs/latest/integrate/redis-data-integration/1.19.1/data-pipelines/transform-examples/remapping-the-output) configuration option.\n\nFor situations where you want to create a new object structure with multiple levels or use calculations for the field values, you can use the\n[`map`](https://redis.io/docs/latest/integrate/redis-data-integration/1.19.1/reference/data-transformation/map)\ntransformation, as described in the following sections.\n\n## Creating multilevel JSON objects\n\nYou can use the `map` transformation to create a new structure for the output data, which can include nested objects and calculated fields. The `map` transformation allows you to define a new structure using an expression language, such as SQL or JavaScript.\n\n```yaml\nname: Create multilevel employee JSON\nsource:\n  db: chinook\n  table: employee\n\ntransform:\n  - uses: map\n    with:\n      expression: |\n        {\n          \"id\": employeeid,\n          \"name\": concat([firstname, ' ', upper(lastname)]),\n          \"address\": {\n            \"street\": address,\n            \"city\": city,\n            \"state\": state,\n            \"postalCode\": postalcode,\n            \"country\": country\n          },\n          \"contact\": {\n            \"phone\": phone,\n            \"safeEmail\": replace(replace(email, '@', '_at_'), '.', '_dot_')\n          }\n        }\n      language: jmespath\n\noutput:\n  - uses: redis.write\n    with:\n      data_type: json\n      key:\n        expression: concat(['emp:', id])\n        language: jmespath\n```\n\n\nThe example above creates a new JSON object with the following structure:\n - A top-level `id` field that is the same as the `employeeid` field in the source table.\n - A `name` field that is a concatenation of the `firstname` and `lastname` fields, with the `lastname` converted to uppercase.\n - An `address` subobject that contains the `address`, `city`, `state`, `postalcode`, and `country` fields.\n - A `contact` subobject that contains the `phone` field and a modified version of the `email` field, where the '@' sign and dots are replaced with '_at_' and '_dot_' respectively.\n\nThe `output` section of the file configures the job to write\nto a JSON object with a custom key. Note that in the `output` section, you must refer to\nfields defined in the `map` transformation, so we use the new name `id`\nfor the key instead of `employeeid`.\n\n\n\nIf you query one of the new JSON objects, you see output like the following:\n\n```bash\n\u003e JSON.GET emp:1 $\n\"[{\\\"id\\\":1,\\\"name\\\":\\\"Andrew ADAMS\\\",\\\"address\\\":{\\\"street\\\":\\\"11120 Jasper Ave NW\\\",\\\"city\\\":\\\"Edmonton\\\",\\\"state\\\":\\\"AB\\\",\\\"postalCode\\\":\\\"T5K 2N1\\\",\\\"country\\\":\\\"Canada\\\"},\\\"contact\\\":{\\\"phone\\\":\\\"+1 (780) 428-9482\\\",\\\"safeEmail\\\":\\\"andrew_at_chinookcorp_dot_com\\\"}}]\"\n```\n\nFormatted in the usual JSON style, the output looks like the sample below:\n\n```json\n{\n  \"id\": 1,\n  \"name\": \"Andrew ADAMS\",\n  \"address\": {\n    \"street\": \"11120 Jasper Ave NW\",\n    \"city\": \"Edmonton\",\n    \"state\": \"AB\",\n    \"postalCode\": \"T5K 2N1\",\n    \"country\": \"Canada\"\n  },\n  \"contact\": {\n    \"phone\": \"+1 (780) 428-9482\",\n    \"safeEmail\": \"andrew_at_chinookcorp_dot_com\"\n  }\n}\n```\n\n## Creating hash structure\n\nThis example creates a new [hash](https://redis.io/docs/latest/develop/data-types/hashes)\nobject structure for items from the `track` table. Here, the `map` transformation uses\n[SQL](https://en.wikipedia.org/wiki/SQL) for the expression because this is often\nmore suitable for hashes or \"flat\"\nJSON objects without subobjects or arrays. The expression renames some of the fields.\nIt also calculates more human-friendly representations for the track duration (originally\nstored in the `milliseconds` field) and the storage size (originally stored in the\n`bytes` field).\n\nThe full example is shown below:\n\n```yaml\nname: Create track hash with calculated fields\nsource:\n  db: chinook\n  table: track\ntransform:\n  - uses: map\n    with:\n      expression:\n          id: trackid\n          name: name\n          duration: concat(floor(milliseconds / 60000), ':', floor(mod(milliseconds / 1000, 60)))\n          storagesize: concat(round(bytes / 1048576.0, 2), 'MB')\n      language: sql\noutput:\n  - uses: redis.write\n    with:\n      connection: target\n      data_type: hash\n      key:\n        expression: concat('track:', id)\n        language: sql\n```\n\nIf you query the data for one of the `track` hash objects, you see output\nlike the following:\n\n```bash\n\u003e hgetall track:16\n1) \"id\"\n2) \"16\"\n3) \"name\"\n4) \"Dog Eat Dog\"\n5) \"duration\"\n6) \"3:35.0\"\n7) \"storagesize\"\n8) \"6.71MB\"\n```\n",
  "tags": ["docs","integrate","rs","rdi"],
  "last_updated": "2026-09-19T17:55:58-07:00"
}
