首页  编辑  

根据字段JSONPath名称从source复制值到destination

Tags: /Node & JS/   Date Created:
如何能过够根据JSONPath名称复制指定名称的属性到另外的对象当中?
假设这样一个方法: copyField(src: any, dst: any, fieldName: string); 
用于复制 src 给定的 fieldName 到 dst 对应的字段当中,其中 fieldName可能包括.号分隔的多个。例:
copyField(src, dst, "name"), 复制 src.name 到 dst.name,
copyField(src, dst, "sub.number" 复制 src.sub.number 到 dst.sub.number
copyField(src, dst, "list.end")复制 src.list[].end 到 dst.list[].end,其中数组每个元素一一对应

请看实现代码:
class dto {
    name: string;
    id: number;
    start: Date;
    list: Array<Info>;
    arr: Info[];
    sub: SubData;

    constructor(data: Partial<dto>) {
        Object.assign(this, data);
    }
}

class Info {
    start: Date;
    end: Date;
    key: string;
}

class SubData {
    address: string;
    start: Date;
    end: Date;
    value: string;
    id: number;
    info: Info;
}

function copyField(src: any, dst: any, fieldName: string) {
    if (fieldName.indexOf('.') === -1) {
        dst[fieldName] = src[fieldName];
        return;
    }

    const key = fieldName.split('.')[0];
    const subKey = fieldName.split('.').slice(1).join('.');
    const srcValue = src[key];

    if (Array.isArray(srcValue)) {
        if (!Array.isArray(dst[key])) {
            dst[key] = [];
        }
        for (let i = 0; i < srcValue.length; i++) {
            if (!dst[key][i]) {
                dst[key][i] = new srcValue[i].constructor();
            } 
            copyField(srcValue[i], dst[key][i], subKey);
        }
    } else if (typeof srcValue === 'object' && srcValue !== null) {
        if (!dst[key]) {
            dst[key] = {};
        }
        copyField(srcValue, dst[key], subKey);
    }
}

// 示例用法
const src = new dto({
    name: 'Source',
    id: 1,
    start: new Date(1),
    arr: [{ start: new Date(2), end: new Date(3), key: 'key1' }, { start: new Date(100), end: new Date(100), key: 'key100' }],
    list: [{ start: new Date(2), end: new Date(3), key: 'key1' }, { start: new Date(100), end: new Date(100), key: 'key100' }],
    sub: { address: '123 Street', start: new Date(4), end: new Date(5), value: 'value1', id: 456, info: { start: new Date(2), end: new Date(3), key: 'key1' } }
});
const target = new dto({
    name: 'Target',
    id: 2,
    start: new Date(6),
    list: [{ start: new Date(7), end: new Date(8), key: 'key2' }, { start: new Date(200), end: new Date(200), key: 'key200' }],
    sub: { address: '456 Street', start: new Date(9), end: new Date(10), value: 'value2', id: 789, info: { start: new Date(7), end: new Date(8), key: 'key2' } }
});

console.log("src: ", src);
console.log("target: ", target);

copyField(src, target, 'name');
copyField(src, target, 'arr.key');
copyField(src, target, 'arr.start');
copyField(src, target, 'list');
copyField(src, target, 'list.end');
copyField(src, target, 'list.key');
copyField(src, target, 'sub.value');
copyField(src, target, 'sub.info');
copyField(src, target, 'sub.info.key');

console.log(target);