将点符号键字符串合并到对象

Merge dot notation key string to Object

我很难过。我有一个看起来像这样的对象:

{
    "sys": {
        "subject": "",
        "preview_text": "",
        "show_view_in_browser": true,
        "email_webview_url": "",
        "rep_alert": true,
        "signatures": {
            "show_joshua": true,
            "show_warren": true,
            "show_david": true
        },
        "email_address": "",
        "show_unsub_link": true,
        "unsubscribe_link": ""
    },
    "pre_intro": {
        "content__rtf": ""
    },
    "pre_intro.button__group": [
        {
            "url": "",
            "name": "",
            "img": ""
        }
    ],
    "content": {
        "introduction__rtf": "",
        "investor-returns": {
            "intro__rtf": "",
            "img__href": "",
            "end__rtf": ""
        },
        "end__rtf": ""
    },
    "content.investor-returns.button__group": [
        {
            "url": "",
            "name": "",
            "img": ""
        }
    ],
    "content.button__group": [
        {
            "url": "",
            "name": "",
            "img": ""
        }
    ]
}

你可以看到我有 pre_intropre_intro.button__group 以及其他一些点符号的键。我如何分解它们以便将它们合并到该对象中,因此输出将是:

"pre_intro": {
  "content__rtf": "",
  "button__group": [
    {  
      "url": "",
      "name": "",
      "img": ""
    }
  ]
},

我尝试使用 lodash 的 _.pickBy() 获取所有包含 '.' 的键,然后尝试将它们缩减为一个对象,但无法使其工作。

_.pickBy(snippets, function(v, k) {
    return _.includes(k, ".");
});

const ref = (obj, str) => {
    return str.split(".").reduce(function(o, x) { return o[x] }, obj);
}

有什么帮助吗?我无法控制给我的原始对象。

使用flat from npm,然后这样做:

import { flatten, unflatten } from 'flat';

const v = { ...yourobject }

const merged = unflatten(flatten(v));

如果您不想使用任何外部库来帮助解决这个问题,这里有一个使用 vanilla Javascript 的算法:

1- 查找所有包含 ..

的键

2- 将密钥拆分为父项和子项

3- 为父键分配一个新的子键

4-删除包含.

的key

const object = {
  "sys": {
    "subject": "",
    "preview_text": "",
    "show_view_in_browser": true,
    "email_webview_url": "",
    "rep_alert": true,
    "signatures": {
      "show_joshua": true,
      "show_warren": true,
      "show_david": true
    },
    "email_address": "",
    "show_unsub_link": true,
    "unsubscribe_link": ""
  },
  "pre_intro": {
    "content__rtf": ""
  },
  "pre_intro.button__group": [{
    "url": "",
    "name": "",
    "img": ""
  }],
  "content": {
    "introduction__rtf": "",
    "investor-returns": {
      "intro__rtf": "",
      "img__href": "",
      "end__rtf": ""
    },
    "end__rtf": ""
  },
  "content.investor-returns.button__group": [{
    "url": "",
    "name": "",
    "img": ""
  }],
  "content.button__group": [{
    "url": "",
    "name": "",
    "img": ""
  }]
};

Object.keys(object).filter(key => key.indexOf(".") >= 0).forEach(key => {
  const combined = key.split(/\./);
  const parent = combined[0];
  const child = combined[1];
  if(!object[parent]) object[parent] = {}; // in case the key doesn't exist yet 

  object[parent][child] = object[key];  // assign the value.
  delete object[key];                   // remove the ugly key
});

console.log(object);

您可以在第一层键中构建一个新对象。

const
    convert = source => Object
        .entries(source)
        .reduce((r, [k, v]) => {
            const
                keys = k.split('.'),
                last = keys.pop();

            keys.reduce((o, k) => o[k] ??= {}, r)[last] = v;
            return r;
        }, {}),
    data = { sys: { subject: "", preview_text: "", show_view_in_browser: true, email_webview_url: "", rep_alert: true, signatures: { show_joshua: true, show_warren: true, show_david: true }, email_address: "", show_unsub_link: true, unsubscribe_link: "" }, pre_intro: { content__rtf: "" }, "pre_intro.button__group": [{ url: "", name: "", img: "" }], content: { introduction__rtf: "", "investor-returns": { intro__rtf: "", img__href: "", end__rtf: "" }, end__rtf: "" }, "content.investor-returns.button__group": [{ url: "", name: "", img: "" }], "content.button__group": [{ url: "", name: "", img: "" }] },
    result = convert(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }