简体   繁体   English

替换 JavaScript object 中的字符串的最佳方法

[英]Best way to replace strings inside an JavaScript object

I have an unknown javascript object (let's call it IncompleteObject just for readability) and an array of IVariables which can be anything, but in the following format:我有一个unknown的 javascript object(为了便于阅读,我们称它为IncompleteObject )和一个IVariables数组,它可以是任何东西,但格式如下:

key: string
value: unknown

Example:例子:

IVariables: IV变量:

[
    { key: 'someObject', value: { some:'value' },
    { key: 'name', value: 'another value' },
    { key: 'lastName', value: 'this variable exists but wont be used' }
]

IncompleteObject:不完整对象:

{
    ID: "SGML",
    SortAs: "{{someObject}}",
    GlossTerm: "Standard Generalized Markup Language",
    Acronym: "The acronym is {{name}}",
    GlossSee: "markup"
}

Expected Result:预期结果:

{
    ID: "SGML",
    SortAs: { 
        some:'value' 
    },
    GlossTerm: "Standard Generalized Markup Language",
    Acronym: "The acronym is another value",
    GlossSee: "markup"
}

The solution i thought was stringfying the object, replacing everything as strings and then trying to parse as JSON again (if it fails, it fails), but i'm wondering if there is a better solution to this... Also idk how to make it so that the SortAs for example becomes an object and not a string我认为的解决方案是 stringfying object,将所有内容替换为字符串,然后再次尝试解析为 JSON(如果失败,则失败),但我想知道是否有更好的解决方案......也不知道如何使 SortAs 例如变成 object 而不是字符串

Thanks!谢谢!

*Notes: *笔记:

  • The object won't necessarily have all variables, like the example. object 不一定具有所有变量,如示例所示。
  • The {{}} format is just an idea, i have no problem changing it since {} is used in JSON {{}} 格式只是一个想法,我可以更改它,因为 {} 在 JSON 中使用

You won't be able add objects during replacing a string, so you'd need do the check if the tag is entire string or not beforehand:您将无法在替换字符串期间添加对象,因此您需要事先检查标签是否为整个字符串:

 const IVariables = [ { key: 'someObject', value: { some:'value' }}, { key: 'name', value: 'another value' }, { key: 'lastName', value: 'this variable exists but wont be used' } ]; const incompleteObject = { ID: "SGML", SortAs: "{{someObject}}", GlossTerm: "Standard Generalized Markup Language", Acronym: "The acronym is {{name}}", GlossSee: "markup {{non-existing-tag}}", blah: "{{name}} and again {{name}}" } //convert array into object const dataVariables = IVariables.reduce((a, b) => (a[b.key] = b.value, a), {}); const reg = /({{([^}]+)}})/; for(let key in incompleteObject) { const data = incompleteObject[key], variable = data.match(reg); if (;variable) continue, if (variable[1] == data) //if entire string a tag; don't use string replace incompleteObject[key] = dataVariables[variable[2]] || variable[1]. else incompleteObject[key] = data,replace(new RegExp(reg, "g"), (a, b. c) => dataVariables[c] || b) } console;log(incompleteObject);

I ended up doing with JSON.stringfy and some regex.我最终使用了 JSON.stringfy 和一些正则表达式。

Here is how i did it:这是我的做法:

const incompleteObject = {
    NoVariable: "Something",
    JustTheObject: "{{someObject}}",
    JustTheString: "{{name}}",
    IntegerValue: "{{integer}}",
    StringInsideOtherString: "Bla bla bla {{name}}",
    ObjectInsideString: "The acronym is {{name}}",
    VariableThatDoesntExist: "{{thisdoesntexist}}",
    ArrayToTestNestedStuff: [
        {
            JustTheObject: "{{someObject}}",
            JustTheString: "{{name}}"
        },
        {
            JustTheObject: "{{someObject}}",
            JustTheString: "{{name}}"
        }
    ]
}

const variablesToSubstitute: Record<string, unknown> = {
    someObject: { some:'value' },
    name: 'another value',
    integer: 2,
    lastName: 'this variable exists but wont be used' 
}
const result = replaceVariables(incompleteObject, variablesToSubstitute)
console.log(JSON.stringify(result, null, 2))
const replaceVariables = (objectToReplace: unknown, variables: Record<string, unknown>) => {
    let stringfiedObject = JSON.stringify(objectToReplace)
    stringfiedObject = replaceEntireProperty(stringfiedObject, variables)
    stringfiedObject = replaceSubstring(stringfiedObject, variables)
    const result = JSON.parse(stringfiedObject)
    return result
}
const replaceEntireProperty = (stringfiedObject: string, variables: Record<string, unknown>) => {
    stringfiedObject = stringfiedObject.replace(/"{{[\w]+}}"/g, (substring: string, ...args: any[]) => {
        const substringWithoutBracesAndComma = substring.substring(3, substring.length-3)
        return JSON.stringify(variables[substringWithoutBracesAndComma] ?? removeAllUnescapedCommas(substring))
    })
    return stringfiedObject
}
const replaceSubstring = (stringfiedObject: string, variables: Record<string, unknown>) => {
    stringfiedObject = stringfiedObject.replace(/{{[\w]+}}/g, (substring: string, ...args: any[]) => {
        const substringWithoutBraces = substring.substring(2, substring.length-2)
        return removeAllUnescapedCommas(JSON.stringify(variables[substringWithoutBraces] ?? substring))
    })
    return stringfiedObject
}
const removeAllUnescapedCommas = (stringToUnescape: string) => {
    return stringToUnescape.replace(/(?<!\\)\"/g, "")
} 

Here is also a GitHub repository with the solution working (Since its typescript, i didnt managed to add the code snippet): https://github.com/vceolin/replace-variables-inside-object这也是一个 GitHub 存储库,解决方案有效(自 typescript 以来,我没有设法添加代码片段): https://github.com/vceolin/replace-variables-inside-object

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM