【问题标题】:What is the best way convert object keys from snake case to camel case and vice versa?将对象键从蛇案例转换为骆驼案例的最佳方法是什么,反之亦然?
【发布时间】:2019-07-23 16:16:53
【问题描述】:

我收到来自服务器的响应,其结构如下:

{
    is_separate_page: true,
    is_blank_page: true,
    is_instructions_page: false,
    is_letter_paper: true,
    is_pressure_seal_paper: false,
    is_mask_ssn_on_letter_paper: true,
    is_mask_ssn_on_pressure_seal_paper: true,
    is_pdf_encrypted_on_letter_paper: false,
    is_pdf_encrypted_on_pressure_seal_paper: true
}

然后我使用以下辅助函数将值转换为驼峰式语法以存储在我的 React 组件状态中:

// Destructuring approach

transformInitialCheckboxesState = data => {
        const {
            is_show_mask_ssn_field: isShowMaskSSNField,
            is_separate_page: isSeparatePage,
            is_blank_page: isBlankPage,
            is_instructions_page: isInstructionsPage,
            is_letter_paper: isLetterPaper,
            is_pressure_seal_paper: isPressureSealPaper,
            is_mask_ssn_on_letter_paper: isMaskSSNonLetterPaper,
            is_mask_ssn_on_pressure_seal_paper: isMaskSSNonPressureSealPaper,
            is_pdf_encrypted_on_letter_paper: isPDFEncryptedOnLetterPaper,
            is_pdf_encrypted_on_pressure_seal_paper: isPDFEncryptedOnPressureSealPaper,
        } = data

        return {
            isShowMaskSSNField,
            isSeparatePage,
            isBlankPage,
            isInstructionsPage,
            isLetterPaper,
            isPressureSealPaper,
            isMaskSSNonLetterPaper,
            isMaskSSNonPressureSealPaper,
            isPDFEncryptedOnLetterPaper,
            isPDFEncryptedOnPressureSealPaper,
        }
    }

对于提交值,我应该根据后端需求执行相反的操作来准备密钥:

    preparePayloadCheckboxesState = data => {
        const {
            isShowMaskSSNField: is_show_mask_ssn_field,
            isSeparatePage: is_separate_page,
            isBlankPage: is_blank_page,
            isInstructionsPage: is_instructions_page,
            isLetterPaper: is_letter_paper,
            isPressureSealPaper: is_pressure_seal_paper,
            isMaskSSNonLetterPaper: is_mask_ssn_on_letter_paper,
            isMaskSSNonPressureSealPaper: is_mask_ssn_on_pressure_seal_paper,
            isPDFEncryptedOnLetterPaper: is_pdf_encrypted_on_letter_paper,
            isPDFEncryptedOnPressureSealPaper: is_pdf_encrypted_on_pressure_seal_paper,
        } = data

        return {
            is_show_mask_ssn_field,
            is_separate_page,
            is_blank_page,
            is_instructions_page,
            is_letter_paper,
            is_pressure_seal_paper,
            is_mask_ssn_on_letter_paper,
            is_mask_ssn_on_pressure_seal_paper,
            is_pdf_encrypted_on_letter_paper,
            is_pdf_encrypted_on_pressure_seal_paper,
        }
    }

问题是:就我的观点而言,它看起来非常相似且可重复,根据您的观点,减少此代码的最佳和最优雅的方法是什么?

【问题讨论】:

  • 请注意,“优雅”和“性能”通常是不相容的。

标签: javascript reactjs performance object


【解决方案1】:

如果要将所有_<alphabet> 替换为<Uppercase Alphabet>,可以循环遍历对象的entries,并将所有_([a-z]) 替换为大写字母。然后使用Object.fromEntries()获取新对象

const fn = key => key.replace(/_([a-z])/g, (_, m) => m.toUpperCase())
const reverse_fn = key => key.replace(/[A-Z]/g, m => `_${m.toLowerCase()}`)

// trasnforms an object based on the replacer function provided
const trasnform = (o, replacer) =>
  Object.fromEntries(
    Object.entries(o).map(([k, v]) => [replacer(k), v])
  )

const input={is_separate_page:true,is_blank_page:true,is_instructions_page:false,is_letter_paper:true,is_pressure_seal_paper:false,is_mask_ssn_on_letter_paper:true,is_mask_ssn_on_pressure_seal_paper:true,is_pdf_encrypted_on_letter_paper:false,is_pdf_encrypted_on_pressure_seal_paper:true} ,
     reverseInput ={isSeparatePage:true,isBlankPage:true,isInstructionsPage:false,isLetterPaper:true,isPressureSealPaper:false,isMaskSsnOnLetterPaper:true,isMaskSsnOnPressureSealPaper:true,isPdfEncryptedOnLetterPaper:false,isPdfEncryptedOnPressureSealPaper:true};

// forward transform
console.log(
  trasnform(input, fn)
)

// reverse transform
console.log(
  trasnform(reverseInput, reverse_fn)
)

反向映射将是类似的。您只需将所有大写字母替换为"_" + <lower case letter>

key.replace(/A-Z/g, m => "_" + m.toLowerCase()

注意:如果不支持Object.fromEntries(),您可以reduce对象的键并创建一个新对象:

const o = {
  is_separate_page: true,
  is_blank_page: true,
  is_instructions_page: false,
  is_letter_paper: true,
  is_pressure_seal_paper: false,
  is_mask_ssn_on_letter_paper: true,
  is_mask_ssn_on_pressure_seal_paper: true,
  is_pdf_encrypted_on_letter_paper: false,
  is_pdf_encrypted_on_pressure_seal_paper: true
}

const trasnform = (o) => 
  Object.keys(o).reduce((acc, k) => {
    const newKey = k.replace(/_([a-z])/g, (_, m) => m.toUpperCase());
    acc[newKey] = o[k];
    return acc;
  }, {})

console.log(trasnform(o))

【讨论】:

  • (或者,如果您已经依赖于 lodash 之类的东西,请使用 mapKeys。)
  • 当然还有k.replace(/([A-Z])/g, (m) => '_' + m.toLowerCase()) 用于相反的情况,如果有任何无关的大写字母将不起作用。
  • @ScottSauyet 我刚刚添加了 :)。此外,反向情况不需要捕获组
  • 时机! :-) 是的,捕获组就是这样。
  • 当然,当您尝试使其与缩写一起使用时,这一切都会失败,例如示例中的"_ssn_"SSN"_pdf_""PDF"。但它可以让你大部分时间到达那里。
【解决方案2】:

您可以创建映射对象和转换函数:

const mapping = {
    "is_show_mask_ssn_field" : "isShowMaskSSNField",
    "is_separate_page": "isSeparatePage",
    ... other properties
}

const fromServer = (data) => {
    let obj = {};
    for (var prop in data) {
        var realName = mapping[prop];
        if (realName) {
            obj[realName] = data[prop];
        }
    }
    return obj;
}

const toServer = (data) => {
    let obj = {};
    for (var serverName in mapping) {
        var realName = mapping[serverName];
        if (data.hasOwnProperty(realName)) {
            obj[serverName] = data[realName];
        }
    }
    return obj;
}

因此,您只需在从端点接收数据后调用 fromServer 并在模型上调用 toServer,然后再将其发送到服务器。

【讨论】:

    猜你喜欢
    • 2019-05-15
    • 2020-05-03
    • 1970-01-01
    • 2020-02-10
    • 2019-10-30
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多