特殊的键值对转换

新手上路,请多包涵

有如下数据:

{
            "AudioLayer.1.ValidChannel": "all",
            "AudioLayer.1.VolumeRate": 1,
            "AudioLayer.2.ValidChannel": "all",
            "AudioLayer.2.VolumeRate": 1,
            "BlendList.1": "RV02",
            "BlendList.2": "RV03",
            "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62",
            "LayoutId": undefined,
            "MixList.1": "RV02",
            "MixList.2": "RV03",
            "VideoLayer.1.FillMode": "fit",
            "VideoLayer.1.HeightNormalized": 1,
            "VideoLayer.1.PositionNormalized.1": 0,
            "VideoLayer.1.PositionNormalized.2": 0,
            "VideoLayer.1.PositionRefer": "topLeft",
            "VideoLayer.1.WidthNormalized": 0.5,
            "VideoLayer.2.FillMode": "fit",
            "VideoLayer.2.HeightNormalized": 1,
            "VideoLayer.2.PositionNormalized.1": 0.5,
            "VideoLayer.2.PositionNormalized.2": 0,
            "VideoLayer.2.PositionRefer": "topLeft",
            "VideoLayer.2.WidthNormalized": 0.5,
        }

需要转换成,下面的格式,需要怎么做啊?

{
    "AudioLayer": [
        {
            "ValidChannel": "all",
            "VolumeRate": 1
        },
        {
            "ValidChannel": "all",
            "VolumeRate": 1
        }
    ],
    "BlendList": [
        "RV02",
        "RV03"
    ],
    "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62",
    "MixList": [
        "RV02",
        "RV03"
    ],
    "VideoLayer": [
        {
            "FillMode": "fit",
            "HeightNormalized": 1,
            "PositionNormalized": [
                0,
                0
            ],
            "PositionRefer": "topLeft",
            "WidthNormalized": 0.5
        },
        {
            "FillMode": "fit",
            "HeightNormalized": 1,
            "PositionNormalized": [
                0.5,
                0
            ],
            "PositionRefer": "topLeft",
            "WidthNormalized": 0.5
        }
    ]
}
阅读 1.9k
3 个回答
function transObj(obj){
    let res = {}
    for(let k in obj){
        setData(res, k, obj[k])
    }
    return res
}
function setData(res, path, value){
    let keyArr = path.split('.'), key, k;

    while(key = keyArr.shift()){
        k = isNaN(key) ? key : (key - 1)
        if(keyArr.length){
            res = res[k] || (res[k] = isNaN(keyArr[0]) ? {} : [])
        }else{
            res[k] = value
        }
    }
}

transObj({
    "AudioLayer.1.ValidChannel": "all",
    "AudioLayer.1.VolumeRate": 1,
    "AudioLayer.2.ValidChannel": "all",
    "AudioLayer.2.VolumeRate": 1,
    "BlendList.1": "RV02",
    "BlendList.2": "RV03",
    "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62",
    "LayoutId": undefined,
    "MixList.1": "RV02",
    "MixList.2": "RV03",
    "VideoLayer.1.FillMode": "fit",
    "VideoLayer.1.HeightNormalized": 1,
    "VideoLayer.1.PositionNormalized.1": 0,
    "VideoLayer.1.PositionNormalized.2": 0,
    "VideoLayer.1.PositionRefer": "topLeft",
    "VideoLayer.1.WidthNormalized": 0.5,
    "VideoLayer.2.FillMode": "fit",
    "VideoLayer.2.HeightNormalized": 1,
    "VideoLayer.2.PositionNormalized.1": 0.5,
    "VideoLayer.2.PositionNormalized.2": 0,
    "VideoLayer.2.PositionRefer": "topLeft",
    "VideoLayer.2.WidthNormalized": 0.5,
})
const datas = {
    "AudioLayer.1.ValidChannel": "all",
    "AudioLayer.1.VolumeRate": 1,
    "AudioLayer.2.ValidChannel": "all",
    "AudioLayer.2.VolumeRate": 1,
    "BlendList.1": "RV02",
    "BlendList.2": "RV03",
    "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62",
    "LayoutId": undefined,
    "MixList.1": "RV02",
    "MixList.2": "RV03",
    "VideoLayer.1.FillMode": "fit",
    "VideoLayer.1.HeightNormalized": 1,
    "VideoLayer.1.PositionNormalized.1": 0,
    "VideoLayer.1.PositionNormalized.2": 0,
    "VideoLayer.1.PositionRefer": "topLeft",
    "VideoLayer.1.WidthNormalized": 0.5,
    "VideoLayer.2.FillMode": "fit",
    "VideoLayer.2.HeightNormalized": 1,
    "VideoLayer.2.PositionNormalized.1": 0.5,
    "VideoLayer.2.PositionNormalized.2": 0,
    "VideoLayer.2.PositionRefer": "topLeft",
    "VideoLayer.2.WidthNormalized": 0.5,
};
const fn = (data) => {
    const result = {};
    for (const _key in data) {
        if (typeof data[_key] !== 'undefined') {
            const [key, index1, objKey, index2] = _key.split('.');

            //这种情况: "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62"
            if (typeof index1 === 'undefined') {
                result[key] = data[_key];
            } else if (typeof objKey === 'undefined') { // 这种情况: "MixList.1": "RV02"
                if (!result[key]) {
                    result[key] = [];
                }
                result[key].push(data[_key]);
            } else if (typeof index2 === 'undefined') { // 这种情况: "VideoLayer.1.HeightNormalized": 1
                if (!result[key]) {
                    result[key] = [];
                }
                if (!result[key][parseInt(index1) - 1]) {
                    result[key][parseInt(index1) - 1] = {};
                }
                result[key][parseInt(index1) - 1][objKey] = data[_key];
            } else {
                if (!result[key]) {
                    result[key] = [];
                }
                if (!result[key][parseInt(index1) - 1]) {
                    result[key][parseInt(index1) - 1] = {};
                }
                if (!result[key][parseInt(index1) - 1][objKey]) {
                    result[key][parseInt(index1) - 1][objKey] = [];
                }
                result[key][parseInt(index1) - 1][objKey].push(data[_key]);
            }
        }
    }
    return result;
};
console.log(fn(datas));

直接运行就可以看到结果,最好能确认一下像VideoLayer.1.WidthNormalized最多有几层.,不确定的话就这么写:

const datas = {
    "AudioLayer.1.ValidChannel": "all",
    "AudioLayer.1.VolumeRate": 1,
    "AudioLayer.2.ValidChannel": "all",
    "AudioLayer.2.VolumeRate": 1,
    "BlendList.1": "RV02",
    "BlendList.2": "RV03",
    "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62",
    "LayoutId": undefined,
    "MixList.1": "RV02",
    "MixList.2": "RV03",
    "VideoLayer.1.FillMode": "fit",
    "VideoLayer.1.HeightNormalized": 1,
    "VideoLayer.1.PositionNormalized.1": 0,
    "VideoLayer.1.PositionNormalized.2": 0,
    "VideoLayer.1.PositionRefer": "topLeft",
    "VideoLayer.1.WidthNormalized": 0.5,
    "VideoLayer.2.FillMode": "fit",
    "VideoLayer.2.HeightNormalized": 1,
    "VideoLayer.2.PositionNormalized.1": 0.5,
    "VideoLayer.2.PositionNormalized.2": 0,
    "VideoLayer.2.PositionRefer": "topLeft",
    "VideoLayer.2.WidthNormalized": 0.5,
};
const fn = (data) => {
    const result = {};
    const maxKeyLong = Object.keys(data).map(a => a.split('.').length).sort((a, b) => a - b).pop();

    for (const key in data) {
        if (typeof data[key] !== 'undefined') {
            const splitKey = key.split('.');

            if (splitKey.length !== maxKeyLong) {
                result[key] = data[key];
            } else {
                const deletedStr = splitKey.pop();

                if (!parseInt(deletedStr) && parseInt(deletedStr) !== 0) {
                    if (!result[splitKey.join('.')]) {
                        result[splitKey.join('.')] = {};
                    }
                    result[splitKey.join('.')][deletedStr] = data[key];
                } else {
                    if (!result[splitKey.join('.')]) {
                        result[splitKey.join('.')] = [];
                    }
                    result[splitKey.join('.')].push(data[key]);
                }
            }
        }
    }
    if (maxKeyLong > 2) {
        return fn(result);
    }
    return result;
};
console.log(fn(datas));

第二种兼容了第一种,第一种写法给你提供一下简单的思路

如果用了lodash,做起来就比较简单了,当然像上面给的答案一样,也可以自己写一个实现。

const data = {
    "AudioLayer.1.ValidChannel": "all",
    "AudioLayer.1.VolumeRate": 1,
    "AudioLayer.2.ValidChannel": "all",
    "AudioLayer.2.VolumeRate": 1,
    "BlendList.1": "RV02",
    "BlendList.2": "RV03",
    "CasterId": "ee08253d-d113-4a0b-9690-61ff3d798b62",
    "LayoutId": undefined,
    "MixList.1": "RV02",
    "MixList.2": "RV03",
    "VideoLayer.1.FillMode": "fit",
    "VideoLayer.1.HeightNormalized": 1,
    "VideoLayer.1.PositionNormalized.1": 0,
    "VideoLayer.1.PositionNormalized.2": 0,
    "VideoLayer.1.PositionRefer": "topLeft",
    "VideoLayer.1.WidthNormalized": 0.5,
    "VideoLayer.2.FillMode": "fit",
    "VideoLayer.2.HeightNormalized": 1,
    "VideoLayer.2.PositionNormalized.1": 0.5,
    "VideoLayer.2.PositionNormalized.2": 0,
    "VideoLayer.2.PositionRefer": "topLeft",
    "VideoLayer.2.WidthNormalized": 0.5,
};
const ret = {};
Object.keys(data).map((key) => {
  const value = data[key];
  key = key.replace(/\.(\d+)(?=\.|$)/g, (_, value) => {
    return '.' + (Number(value) - 1).toString();
  });
  _.set(ret, key, value);
});
console.log(ret); // 结果
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题