首页 > 解决方案 > 格式化 JavaScript 对象占位符和替换对象

问题描述

我有一个带有占位符 ${var_name} 的对象

{
  "name": "${title}",
  "description": "${description}",
  "provider": {
    "@type": "Organization"
  },
  "hasInstance": [
    {
      "@type": "instance",
      "mode": [
        "study",
        "online"
      ],
      "offers": {
        "@type": "Offer",
        "price": "${price}"
      }
    }
  ]
}

和一个替换的对象

{
  "title": "aaa",
  "description": "bbb \n ccc",
  "price": 100,
  "history": "ddd"
}

替换占位符后,预期结果:

{
  "name": "aaa",
  "description": "bbb \n cc",
  "provider": {
    "@type": "Organization"
  },
  "hasInstance": [
    {
      "@type": "instance",
      "mode": [
        "study",
        "online"
      ],
      "offers": {
        "@type": "Offer",
        "price": 100
      }
    }
  ]
}

我的想法是:

问题是:JSON.parse将失败,数据包含 JSON 转义,例如:"、\、/、\b、\f、\n、\r、\t

function replace(template, data) {
    let templateString = JSON.stringify(template);
    var placeholders = templateString.match(/\${([\w\.\:]+)}/g);

    placeholders.forEach(placeholder => {
        // convert ${var_name} to var_name, then assign to phText
        let phText = placeholder.substring(2,placeholder.length - 1);
        if(data[phText]) {
            templateString = templateString.replace(placeholder, data[phText]);
        }
    });

    return JSON.parse(templateString);
}

标签: javascriptjson

解决方案


在不解析 JSON 的情况下,递归扫描对象,搜索占位符模式,并将其替换为新值:

function scanObjectAndReplace(newValues, obj, key=false){
    if(key && typeof(obj[key])==='string'){
        let str = obj[key];
        let i1=str.indexOf("${"); 
        let i2=str.indexOf("}");
        if(i1>=0 && i2>i1) {
            let keyname = str.substring(i1+2, i2);
            let substr = str.substring(i1, i2+1);
            if(!(keyname in newValues)) {console.log(`key ${keyname} not exist in new valuse.`);return}
            if(i1==0 && i2==str.length-1) // if value include only the placeholder then set a new value
                obj[key] = newValues[keyname];
            else
                obj[key] = str.replace(substr,values[keyname]); // otherwise treat it as string replacment
            console.log(`oldval=${str}, newval=${obj[key]}, type=${typeof(obj[key])}`)
        }
    } else {
        let objval = key ? obj[key] : obj;
        if (Object.keys(Object(objval)).length>0) {
            for (const k of Object.keys(objval)){
                console.log(k);
                scanObjectAndReplace(newValues,objval, k);
            }
        }
    }
}
scanObjectAndReplace(new_values, obj); // call the function

您可以将 regexp 用于较短的版本,但我的函数更易于调试。


推荐阅读