如何根据 JavaScript 中的键转换对象?

How to convert object based on keys in JavaScipt?

我有以下格式的对象。我在处理了一些数据之后得到了这个对象,并且密钥已经从上述数据中检索到了。这些键指的是一个数据结构,用“.”表示。句号。我正在寻找一种可以将此对象更改为第二个对象结构的方法,因为这样可以更轻松地将此数据保存在后端。

    {
   "pageId":"6103a64eaa0f0228d5487d8d",
   "answer":{
      "PremiumServices:AmazonPrime":"1",
      "paymentMethod:Paypal:PaypalUsageCode":[
         "2"
      ],
      "PaymentsToIncurCode":[
         "1",
         "2"
      ],
      "null":[
         "10",
         "4",
         "7"
      ],
      "paymentMethod:mobileWalletCodes":[
         "10"
      ],
      "paymentMethod:mobileWalletCodes.0":[
         "17"
      ],
      "paymentMethod:mobileWalletCodes.1":[
         "17"
      ],
      "paymentMethod:mobileWalletCodes.2":[
         "16"
      ],
      "paymentMethod:mobileWalletCodes.3":[
         "16"
      ]
   }
},

我想把它转换成下面的格式。

{
  "pageId": "6103a64eaa0f0228d5487d8d",
  "answer": {
    "PremiumServices": {
      "AmazonPrime": "1"
    },
    "paymentMethod": {
      "mobileWalletCodes": {
        "0": [
          "17"
        ],
        "1": [
          "17"
        ],
        "2": [
          "16"
        ],
        "3": [
          "16"
        ]
      }
    },
    "PaymentsToIncurCode": [
      "1",
      "2"
    ],
    "PaymentsToIncuCode": [
      "10",
      "4",
      "7"
    ]
  }
}

是否有库或函数可以将第一个对象转换为第二个对象的格式?

属性有多个自定义转换步骤。这是我能够实现的最通用的方法:

const json = `{
   "pageId":"6103a64eaa0f0228d5487d8d",
   "answer":{
      "PremiumServices:AmazonPrime":"1",
      "paymentMethod:Paypal:PaypalUsageCode":[
         "2"
      ],
      "PaymentsToIncurCode":[
         "1",
         "2"
      ],
      "null":[
         "10",
         "4",
         "7"
      ],
      "paymentMethod:mobileWalletCodes":[
         "10"
      ],
      "paymentMethod:mobileWalletCodes.0":[
         "17"
      ],
      "paymentMethod:mobileWalletCodes.1":[
         "17"
      ],
      "paymentMethod:mobileWalletCodes.2":[
         "16"
      ],
      "paymentMethod:mobileWalletCodes.3":[
         "16"
      ]
   }
}`;
const data = JSON.parse(json);

const result = {
  pageId: data.pageId,
  answer: {
    PremiumServices: Object
      .fromEntries(Object
        .entries(data.answer)
        .filter(([key]) =>
          key.startsWith('PremiumServices')
        ).map(([key, value]) =>
          [key.split(':')[1], value]
        )
      ),
    paymentMethod: Object
      .fromEntries(Object
        .entries(data.answer)
        .filter(([key]) =>
          key.startsWith('paymentMethod:mobileWalletCodes.')
        ).map(([key, value]) =>
          [key.split('.')[1], value]
        )
      ),
    PaymentsToIncurCode: data.answer.PaymentsToIncurCode,
    PaymentsToIncuCode: data.answer.null
  }
};
console.log(result);

const resultJson = JSON.stringify(result);

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

这是一个使用ramda

的函数式递归方法
const convertObjectStructure = R.compose(
  R.reduce(R.mergeDeepWith((x, y) => R.is(Object, x) && R.is(Array, y) ? x : R.is(Object, y) && R.is(Array, x) ? y : R.concat(x, y)), {}),
  R.map(([k, v]) => R.assocPath(R.split(/\.|:/, k), R.when(R.both(R.is(Object), R.compose(R.complement, R.is)(Array)), convertObjectStructure)(v), {})),
  R.toPairs
)

convertObjectStructure(JSON.parse(json))

没有我希望的那么干净,但是已经是午夜了。

playground

中查看

更新 #1

The output is not the sames as the OP's.. – Keith

const renameKeysDeep = R.curry((mapping, input) => R.compose(
  R.reduce((acc, [k, v]) => {
    if (!(k in mapping)) return {...acc, [k]: v};
    if (R.is(Object)(mapping[k])) return {...acc, [k]: renameKeysDeep(mapping[k], v)};
    return {...acc, [mapping[k]]: v};
  }, {}),
  R.toPairs
)(input))

const convertObjectStructure = R.compose(
  R.reduce(R.mergeDeepWith((x, y) => R.is(Object, x) && R.is(Array, y) ? x : R.is(Object, y) && R.is(Array, x) ? y : R.concat(x, y)), {}),
  R.map(([k, v]) => R.assocPath(R.split(/\.|:/, k), R.when(R.both(R.is(Object), R.compose(R.complement, R.is)(Array)), convertObjectStructure)(v), {})),
  R.toPairs
)

// Usage
R.compose(
  convertObjectStructure,
  renameKeysDeep({'answer': {'null': 'PaymentsToIncuCode'}}),
  R.dissocPath(['answer', 'paymentMethod:Paypal:PaypalUsageCode']),
)(JSON.parse(json))

playground

中查看

我终于找到了解决问题的最佳方法。 Dot-Object 可以使用点符号转换 JavaScript 个对象。

var dot = require('dot-object');

var row = {
  'id': 2,
  'contact.name.first': 'John',
  'contact.name.last': 'Doe',
  'contact.email': 'example@gmail.com',
  'contact.info.about.me': 'classified',
  'devices[0]': 'mobile',
  'devices[1]': 'laptop',
  'some.other.things.0': 'this',
  'some.other.things.1': 'that'
};

dot.object(row);

console.log(row);
// result will be as below
{
  "id": 2,
  "contact": {
    "name": {
      "first": "John",
      "last": "Doe"
    },
    "email": "example@gmail.com",
    "info": {
      "about": {
        "me": "classified"
      }
    }
  },
  "devices": [
    "mobile",
    "laptop"
  ],
  "some": {
    "other": {
      "things": [
        "this",
        "that"
      ]
    }
  }
}