Soviut
Soviut

Reputation: 91555

How to transform a JSON array nested inside an object inside another array in Postgres?

I'm using Postgres 9.6 and have a JSON field called credits with the following structure; A list of credits, each with a position and multiple people that can be in that position.

[
  {
    "position": "Set Designers",
    people: [
      "Joe Blow",
      "Tom Thumb"
    ]
  }
]

I need to transform the nested people array, which are currently just strings representing their names, into objects that have a name and image_url field, like this

[
  {
    "position": "Set Designers",
    people: [
      { "name": "Joe Blow", "image_url": "" },
      { "name": "Tom Thumb", "image_url": "" }
    ]
  }
]

So far I've only been able to find decent examples of doing this on either the parent JSON array or on an array field nested inside a single JSON object.

So far this is all I've been able to manage and even it is mangling the result.

UPDATE campaigns
  SET credits = (
    SELECT jsonb_build_array(el)
    FROM jsonb_array_elements(credits::jsonb) AS el
  )::jsonb
;

Upvotes: 1

Views: 211

Answers (1)

klin
klin

Reputation: 121604

Create an auxiliary function to simplify the rather complex operation:

create or replace function transform_my_array(arr jsonb)
returns jsonb language sql as $$
    select case when coalesce(arr, '[]') = '[]' then '[]'
    else jsonb_agg(jsonb_build_object('name', value, 'image_url', '')) end
    from jsonb_array_elements(arr)  
$$;

With the function the update is not so horrible:

update campaigns
  set credits = (
    select jsonb_agg(jsonb_set(el, '{people}', transform_my_array(el->'people')))
    from jsonb_array_elements(credits::jsonb) as el
  )::jsonb
;

Working example in rextester.

Upvotes: 3

Related Questions