javascript - 在嵌套的 json 对象中按键获取值并替换为第二个 json 值
问题描述
我有一个 json 对象(firstObj)它可以嵌套,我有一个包含键/值对的第二个对象。我想通过匹配值将第二个对象的值替换为第一个对象的值并执行它的操作。
let firstObj = {
amount_money: {
amount: {
mapped_field: 'payment_amt',
operation: '/10'
},
currency: {
mapped_field: 'payment_cur',
operation: null
}
},
source_id: {
mapped_field: 'request_id',
operation: null
},
ship: [
{ mapped_field: 'ship_country[0]', operation: null },
{ mapped_field: 'ship_country[1]', operation: null }
]
};
我的第二个对象
let secondObj = {
payment_amt: 100,
payment_cur: 'USD',
request_id: '123ASD',
ship_country: [
{ code: 'USA', Title: 'America' },
{ code: 'UK', Title: 'England' }
]
};
我想要这样的东西
{
amount_money: {
amount: 10
currency: 'USD'
},
source_id: '123ASD',
ship: [ {America: 'USA'}, {England: 'UK'}]
}
非常感谢您的热心帮助,谢谢!
解决方案
解决更新的问题
// const objectScan = require('object-scan');
const myTemplate = { amount_money: { amount: { mapped_field: 'payment_amt', operation: '/10' }, currency: { mapped_field: 'payment_cur', operation: null } }, source_id: { mapped_field: 'request_id', operation: null }, ship: [{ mapped_field: 'ship_country[0]', operation: null }, { mapped_field: 'ship_country[1]', operation: null }] };
const myVariables = { payment_amt: 100, payment_cur: 'USD', request_id: '123ASD', ship_country: [{ code: 'USA', Title: 'America' }, { code: 'UK', Title: 'England' }] };
const apply = (input, operation) => {
if (operation === null) {
return input;
}
const action = /(?<op>[/+])(?<v>\d+)/g.exec(operation);
if (action === null) {
throw new Error(`Unknown operation: ${operation}`);
}
if (action.groups.op === '/') {
return input / action.groups.v;
}
// action.groups.op === '+'
return input + action.groups.v;
};
const compile = objectScan(['**.mapped_field'], {
rtn: 'count',
filterFn: ({ gparent, gproperty, parent, value, context }) => {
const data = objectScan([value], { rtn: 'value', abort: true })(context);
if (data === undefined) {
return false;
}
gparent[gproperty] = apply(data, parent.operation);
return true;
}
});
console.log(compile(myTemplate, myVariables));
// => 5
console.log(myTemplate);
// => { amount_money: { amount: 10, currency: 'USD' }, source_id: '123ASD', ship: [ { code: 'USA', Title: 'America' }, { code: 'UK', Title: 'England' } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@16.0.2"></script>
免责声明:我是对象扫描的作者
旧答案(问题的预编辑)
这是使用object-scan的通用解决方案。
// const objectScan = require('object-scan');
const template = { amount_money: { amount: { mapped_field: 'payment_amt', operation: '/10' }, currency: { mapped_field: 'payment_cur', operation: null } }, source_id: { mapped_field: 'request_id', operation: null } }
const values = { payment_amt: 100, payment_cur: 'USD', request_id: '123ASD' };
const apply = (input, operation) => {
if (operation === null) {
return input;
}
const action = /(?<op>[/+])(?<v>\d+)/g.exec(operation);
if (action === null) {
throw new Error(`Unknown operation: ${operation}`);
}
if (action.groups.op === '/') {
return input / action.groups.v;
}
// action.groups.op === '+'
return input + action.groups.v;
};
const compile = objectScan(['**.*.mapped_field'], {
rtn: 'count',
filterFn: ({ gparent, gproperty, parent, value, context }) => {
if (value in context) {
gparent[gproperty] = apply(context[value], parent.operation);
return true;
}
return false;
}
});
console.log(compile(template, values));
// => 3
console.log(template);
// => { amount_money: { amount: 10, currency: 'USD' }, source_id: '123ASD' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@16.0.2"></script>
免责声明:我是对象扫描的作者
重要的:
- 请注意,这确实会修改模板对象。如果不需要,您可以克隆它。
- 您可以使用 eval,但它被认为是危险的。这需要做更多的工作,但您可能应该自己实现所有支持的操作,就像我在“应用”函数中开始的那样。
- 您也许可以使用例如safe-eval,但我没有使用它的经验,也不知道它有多安全。如果您担心任何形式的注入攻击,请不要使用它。
编辑(根据评论中的要求)
这是如何工作的:
apply
是一个辅助函数,接受输入和操作。我们使用正则表达式来确定运算符,然后将其应用于输入compile
是核心逻辑。我们以 为目标字段**.*.mapped_field
,其中 single*
确保我们以对象而不是数组为目标- 在
filterFn
我们检查值是否已知context
(即values
)。如果是这种情况,则使用祖父母 (gparent
) 和祖属性 (gproperty
) 更新值。的所有参数filterFn
都是相对于目标的(在这种情况下mapped_field
) count
只是返回值(在这种情况下,多久true
返回一次filterFn
这在对象扫描中都有详细记录。看看那里。放入日志语句也可能对您的理解有很大帮助!
推荐阅读
- c++ - 如何在 C++ 中并行处理类的实例?
- c# - 获取当前月份和年份的所有交易,避免显示上一年的交易
- android - 如何将 Admob Native Advanced Ads 放置在回收站视图 android 中?
- c++ - wintun:ERROR_INVALID_PARAMETER 注册环形缓冲区
- python - 如何将 Python3 中另一个文件中的函数内部的变量调用到当前文件中?
- c# - c# 中是否有一种方法可以检查字符串是否为有效的十六进制数?
- c# - 从 Datagridview 到其他 datagridview 添加在旧行下
- css - 菜单悬停颜色
- c - IPC消息队列溢出后果
- centos7 - 错误:创建输出文件 /var/lib/logrotate.status.tmp 时出错:权限被拒绝