UPDATE
As @Matt pointed out g:jsonTemplate is a list that needs to be copied. I originally thought that multiline strings were strings and overlooked the varible assignment detail after debugging. The doc for the mutiline string is :h let-heredoc.
There was another issue, unrelated to this question, that I solved thanks to @D. Ben Knoble's answer. I misunderstood the docs when trying to make the search pattern case sensitive and used a non-existant 'C' flag for substitute(), instead of prepending the search pattern arg with '\C' (and using single quotes). After reading 27.1 from :h usr_27, I realised that the cause was a forgotten setting in my .vimrc (set ignorecase).
Working solution:
function InsertJsonObj() let date = trim(system('date +"%T"')) let uuid = GetUUID() let copy = copy(g:jsonTemplate) " now using copy() "next 2 lines: substituted double quotes for single quotes, removed erroneous flag and prepended pat with \C to make it case sensitive. let copy[1] = substitute(copy[1], '\CUUID', uuid, '') let copy[2] = substitute(copy[2], '\CDATE', date, '') call append(line('.'), copy) endfunction ORIGINAL POST
The goal:
function GetUUID() return trim(system('uuidgen')) "a script endfunction function InsertJsonObj() let date = trim(system('date +"%T"')) let uuid = GetUUID() "call append(line('.'), GetUUID()) "this line appends a different value every time let copy = g:jsonTemplate let copy[1] = substitute(copy[1], "UUID", uuid, "C") let copy[2] = substitute(copy[7]copy[2], "DDDD", date, "C") call append(line('.'), copy) endfunction let g:jsonTemplate =<< END { "id": "91fe667f-7caf-47e5-b650-da1bc7532d8c""UUID", "date": ["15:21:59"]["DDDD"], }, END