SOURCE

let obj = {
    "stepInfo_companyChannel": [
        "1",
        "2",
        "3"
    ],
    "stepInfo_promotionSteps<0>_companyFirstChargeAmount": 12,
    "stepInfo_promotionSteps<0>_companyFirstChargeAmount1": 122,
    "stepInfo_promotionSteps<0>_mainStep": true,
    "stepInfo_promotionSteps<0>_returnBcoupon": true,
    "stepInfo_promotionSteps<0>_smsTemplateId": false,
    "stepInfo_promotionSteps<0>_push": false,
    "stepInfo_promotionSteps<0>_returnBcoupon<1>_batchId": "1234",
    "stepInfo_promotionSteps<0>_returnBcoupon<1>_number": 1233,
    "stepInfo_promotionSteps<0>_returnBcoupon<0>_fastCarBatchId": "1228",
    "stepInfo_promotionSteps<0>_returnBcoupon<0>_fastCarNumber": 124,
    "stepInfo_promotionSteps<0>_returnBcoupon<0>_batchId": "11",
    "stepInfo_promotionSteps<0>_returnBcoupon<0>_number": 129,
    "stepInfo_promotionSteps<0>_returnBcoupon<0>_replaceFastCarCoupon": 1,
    "stepInfo_promotionSteps<1>_companyFirstChargeAmount": 99,
    "stepInfo_promotionSteps<1>_companyFirstChargeAmount1": 990,
    "stepInfo_promotionSteps<1>_mainStep": true,
    "stepInfo_promotionSteps<1>_returnBcoupon": true,
    "stepInfo_promotionSteps<1>_sms": false,
    "stepInfo_promotionSteps<1>_push": false,
    "stepInfo_promotionSteps<1>_returnBcoupon<1>_batchId": "555",
    "stepInfo_promotionSteps<1>_returnBcoupon<1>_number": 777,
    "stepInfo_promotionSteps<1>_returnBcoupon<1>_replaceFastCarCoupon": 1,
    "stepInfo_promotionSteps<1>_returnBcoupon<0>_fastCarBatchId": "88",
    "stepInfo_promotionSteps<1>_returnBcoupon<0>_fastCarNumber": 665,
    "stepInfo_promotionSteps<1>_returnBcoupon<1>_fastCarBatchId": "44",
    "stepInfo_promotionSteps<1>_returnBcoupon<1>_fastCarNumber": 444,
    "stepInfo_stepCrowdTag": "1001271955",
    "stepInfo_promotionSteps<1>_returnBcoupon<0>_batchId": "9999",
    "stepInfo_promotionSteps<1>_returnBcoupon<0>_number": 1292929,
    "stepInfo_promotionSteps<1>_returnBcoupon<0>_replaceFastCarCoupon": 1
}
const replaceNullProperty = (obj) => {
	let nullData = [undefined,null,'null',"undefined",'']
	for( let i in obj ){//遍历对象中的属性
        if(obj[i].constructor === Object){
            Object.keys(obj[i]).map(item=>{
                replaceNullProperty(obj[i][item])
            })
        }else if(obj[i].constructor === Array){
           let len = obj[i].length
           for(let j = 0; j < len ; j++){
            //    console.log(obj[i][j])
               if( nullData.includes(obj[i][j])){
                   obj[i][j] = {}
               }else if(obj[i][j].constructor === Array || obj[i][j].constructor === Object){
                   replaceNullProperty(obj[i][j])
               }
           }
        }
    }
	return obj
}
function _basePath(path) {
    // 若是数组,则直接返回
    if (Array.isArray(path)) return path
    // 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'  //   由于[0] 会被antd form解析成路径  所以将[0]改为'0' 
    return path.replace(/\</g, '_').replace(/\>/g, '').split('_')
}


function setObj(object, path, value) {
    if (typeof object !== 'object') return object;
    _basePath(path).reduce((o, k, i, _) => {
        if (i === _.length - 1) { // 若遍历结束直接赋值
            o[k] = value
            return 
        } else if (k in o) { // 若存在对应路径,则返回找到的对象,进行下一次遍历
            return o[k]
        } else { // 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
            o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
            return o[k]
        }
    }, object)

    // 返回object
    return object;
}


const getRawType = (val) => {
    //   返回 某个对象数据类型的字符串 [object Date]  ==>  Object
    //   -1代表截取到倒数第一位(不含)
    return Object.prototype.toString.call(val).slice(8,-1)
}
const isPlainObject = (val) => {
    // 判断是否是一个对象
    return getRawType(val) === 'Object'
}

const isPlainObjectOrArray = (val) => {
    // 判断是否是一个对象 或者是个 数组
    return isPlainObject(val) || Array.isArray(val)
}
let newObj = []
Object.keys(obj).map((item,index)=>{
    newObj.push(setObj({},item , obj[item]))
})
const merge = (object, ...sources) => {
    for (const source of sources) {
        for (const key in source) {
            if (source[key] === undefined && key in object) {
                continue
            }
            if (isPlainObjectOrArray(source[key])) {
                if (isPlainObjectOrArray(object[key]) && getRawType(object[key]) === getRawType(source[key])) {
                    if (isPlainObject(object[key])) {
                        merge(object[key], source[key])
                    } else {
                        //  console.log("哈哈哈",object[key],source[key])
                        object[key] = mergeArr(object[key],source[key])
                    }
                } else {
                    object[key] = source[key]
                }
            } else {
                object[key] = source[key]
            }
        }
    }  
}

function mergeArr(arr1,arr2){
    const key2=Object.keys(arr2[0])[0]
    if( Array.isArray(arr2[0][key2]) ){
        Object.keys(arr1[0]).forEach(item=>{
            if(item==key2){
                if(Array.isArray(arr1[0][key2])){
                    mergeArr(arr1[0][key2],arr2[0][key2])
                }else{
                    arr1[0][key2]=arr2[0][key2]
                }
            }
        })
    }else{
        // console.log(arr1)
         Object.assign(arr1[0],arr2[0])
    }
    return arr1
}
let noNullArr = replaceNullProperty(newObj)
// console.log(newObj)
let object = {}
merge(object,...noNullArr);
console.log(";藕节",JSON.stringify(object))
console 命令行工具 X clear

                    
>
console