{"ScriptPreparationCode":"function isStringOrNumber(value){\r\n return (\r\n value !== undefined \u0026\u0026\r\n value !== null \u0026\u0026\r\n !Number.isNaN(value) \u0026\u0026\r\n (typeof value === \u0027string\u0027 || typeof value === \u0027number\u0027)\r\n );\r\n}\r\n\r\nfunction recursiveReplaceTemplateStrings(\r\n obj,\r\n templateDict,\r\n ignoreFieldFunc,\r\n currentPath) {\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map((item) =\u003E\r\n recursiveReplaceTemplateStrings(item, templateDict, ignoreFieldFunc, currentPath),\r\n );\r\n }\r\n\r\n if (typeof obj === \u0027object\u0027 \u0026\u0026 obj !== null) {\r\n var newObj = {};\r\n\r\n Object.keys(obj).forEach((key) =\u003E {\r\n var value = obj[key];\r\n var keyPath = currentPath ? \u0060${currentPath}.${key}\u0060 : key;\r\n\r\n if (typeof value !== \u0027string\u0027) {\r\n // Recursively call the function for non-string values\r\n newObj[key] = recursiveReplaceTemplateStrings(\r\n obj[key],\r\n templateDict,\r\n ignoreFieldFunc,\r\n keyPath,\r\n );\r\n return;\r\n }\r\n\r\n if (!ignoreFieldFunc?.(key, currentPath)) {\r\n var regex = /\\[%([^%]\u002B)%]/g;\r\n\r\n newObj[key] = value.replace(regex, (_, dictKey) =\u003E {\r\n var actualValue = templateDict[dictKey];\r\n\r\n return isStringOrNumber(actualValue) ? \u0060${actualValue}\u0060 : \u0027\u0027;\r\n });\r\n\r\n return;\r\n }\r\n\r\n newObj[key] = value;\r\n });\r\n\r\n return newObj;\r\n }\r\n\r\n return obj;\r\n}\r\n\r\nfunction jsonReplaceTemplateStrings(\r\n obj,\r\n templateDict,\r\n ignoreFieldFunc,\r\n currentPath,\r\n) {\r\n var jsonStr = JSON.stringify(obj, (key, value) =\u003E {\r\n if (typeof value === \u0027string\u0027) {\r\n if (!ignoreFieldFunc?.(key, currentPath)) {\r\n var regex = /\\[%([^%]\u002B)%]/g;\r\n return value.replace(regex, (_, dictKey) =\u003E {\r\n const actualValue = templateDict[dictKey];\r\n return isStringOrNumber(actualValue) ? \u0022\u0022 \u002B actualValue : \u0027\u0027;\r\n });\r\n }\r\n }\r\n return value;\r\n });\r\n return JSON.parse(jsonStr);\r\n\r\n}\r\n\r\n\r\nvar ignoreFieldFunc = (key, path) =\u003E {\r\n const nonInterpolatedFields = [\u0027id\u0027, \u0027type\u0027, \u0027data.id\u0027];\r\n return nonInterpolatedFields.some((val) =\u003E val === key || val === \u0060${path}.${key}\u0060);\r\n};\r\nvar obj = {\r\n id: \u0027some_id_[%some_id_part%]\u0027,\r\n type: \u0027flex\u0027,\r\n title: \u0027Hello, [%user_name%]!\u0027,\r\n data: {\r\n id: \u0027some_nested_id_[%some_nested_id_part%]\u0027,\r\n options: [{\r\n id: \u0027some_nested_array_id_[%some_nested_array_id_part%]\u0027,\r\n text: \u0027option [%some_option_part%]\u0027,\r\n }, ],\r\n },\r\n};\r\nvar templateDict = {\r\n some_id_part: \u0027unexpected_id_part\u0027,\r\n some_nested_id_part: \u0027unexpected_nested_id_part\u0027,\r\n some_nested_array_id_part: \u0027unexpected_nested_array_id_part\u0027,\r\n user_name: \u0027Jane\u0027,\r\n some_option_part: \u0027A\u0027,\r\n};\r\nvar expected = {\r\n id: \u0027some_id_[%some_id_part%]\u0027,\r\n type: \u0027flex\u0027,\r\n title: \u0027Hello, Jane!\u0027,\r\n data: {\r\n id: \u0027some_nested_id_[%some_nested_id_part%]\u0027,\r\n options: [{\r\n id: \u0027some_nested_array_id_[%some_nested_array_id_part%]\u0027,\r\n text: \u0027option A\u0027\r\n }],\r\n },\r\n};","TestCases":[{"Name":"JSON.parse","Code":"jsonReplaceTemplateStrings(obj, templateDict, ignoreFieldFunc)","IsDeferred":false},{"Name":"Recursive interpolate","Code":"recursiveReplaceTemplateStrings(obj, templateDict, ignoreFieldFunc)","IsDeferred":false}]}