json键替换为overrides部分

时间:2019-03-14 04:05:59

标签: node.js

我有一个配置json文件,这是一个示例

{
  "version": "1.0",
  "producer": {
    "name": "app_name_{{ ENVIRONMENT }}_producer",
    "kms_key_alias": "alias/app_name_{{ ENVIRONMENT }}_producer_key",
    "shards": 1,
    "subscriptions": [
      {
        "name": "app_name1_{{ ENVIRONMENT }}_consumer",
        "account_id": "123456789012",
        "active": true
      },
      {
        "name": "app_name2_{{ ENVIRONMENT }}_consumer",
        "account_id": "987654321098",
        "active": true
      }
    ]
  },
  "consumers": [
    {
      "name": "app_name_{{ ENVIRONMENT }}_consumer",
      "kms_key_alias": "alias/app_name_{{ ENVIRONMENT }}_consumer_key",
      "shards": 1
    }
  ],
  "overrides": {
    "prod": {
      "producer": {
        "shards": 2,
        "subscriptions": [
          {
            "name": "app_name1_{{ ENVIRONMENT }}_consumer",
            "account_id": "123456789012",
            "active": false
          }
        ]
      },
      "consumers": [
        {
          "name": "app_name_{{ ENVIRONMENT }}_consumer",
          "shards": 3
        }
      ]
    }
  }
}

我的目标是为该环境生成最终配置。环境是变量。

prod的配置将有所不同。例如prod中的producer.shards将是2,而不是1。

此过程是,读取json文件(属于producerconsumers的一部分,然后保存到新变量new_json中。这可以理解为默认值。

{
  "producer": {
     ...
  }
  consumers": {
    ...
  }
} 

然后读取覆盖会话,如果环境为prod,它将覆盖相关键中的值。

我写了forEach代码以读取overrides中的每个键,然后我需要确认键是列表或映射,然后转到该部分的结尾,替换{{1 }}。

new_json

示例json是一个简单的json。真正的json有几百行。因此,遍历每个密钥不是有效的方法。

是否有任何快速/智能方法来覆盖对const json = JSON.parse(template) if ({}.hasOwnProperty.call(overrides, environment)) { const env = overrides[environment]; Object.keys(env).forEach((key){ ... } } 的覆盖中的任何键?

更新#1

使用Object.assign(),我仍然需要遍历每个键,否则,我得到的键会更少。

例如,使用下面的代码,我在new_json列表中所占的比例减少了。

subscriptions

更新#2

感谢您将我指向lodash.defaultsDeep,但在合并列表中的地图时,它必须在同一位置一对一匹配。

使用存在作为示例,如果我稍微调整$ cat a.js const fs = require('fs'); const swig = require('swig-templates'); const environment='prod'; let template = swig.compileFile("jsoncontent.json"); template = template({ ENVIRONMENT: environment, }); const json = JSON.parse(template); Object.assign(json.producer, json.overrides.prod.producer) delete json.overrides console.log(JSON.stringify(json, null, 2)); $ node a.js { "version": "1.0", "producer": { "name": "app_name_prod_producer", "kms_key_alias": "alias/app_name_prod_producer_key", "shards": 2, "subscriptions": [ { "name": "app_name1_prod_consumer", "account_id": "123456789012", "active": false } ] }, "consumers": [ { "name": "app_name_prod_consumer", "kms_key_alias": "alias/app_name_prod_consumer_key", "shards": 1 } ] } ,则订阅的第一个列表,名称从overrides更改为app_name1

app_name2

结果将是:

"overrides": {
    "prod": {
      "producer": {
        "shards": 2,
        "subscriptions": [
          {
            "name": "app_name2_{{ ENVIRONMENT }}_consumer",
            "account_id": "123456789012",
            "active": false
          }
        ]
      }
  }

现在有两个{ shards: 2, subscriptions: [ { name: 'app_name2_prod_consumer', account_id: '123456789012', active: false }, { name: 'app_name2_prod_consumer', account_id: '987654321098', active: true } ], name: 'app_name_prod_producer', kms_key_alias: 'alias/app_name_prod_producer_key' }

1 个答案:

答案 0 :(得分:2)

Object.assign似乎正是您需要的。

示例:

var o1 = {
  a: 1,
  b: 2
}

var override = {
  a: 9
}

Object.assign(o1, override)
console.log(o1) // {a: 9, b: 2}

编辑

Object.assign仅循环通过根级别。
对于深度分配,您可以使用lodash.defaultsDeep

var env = _.defaultsDeep(json.overrides.prod.producer, json.producer)