title: json keys replacement with overrides part
body: <p>I have a configuration json file, here is a sample</p>
  
  <pre><code>{
    "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
          }
        ]
      }
    }
  }
  </code></pre>
  
  <p>My target is to generate a final configuration for that environment. Environment is a variable.</p>
  
  <p>The configuration for <code>prod</code> will be different. Such as <code>producer.shards</code> in prod will be 2, not 1.</p>
  
  <p>The process is, read the json file, part of <code>producer</code> and <code>consumers</code>, save to a new variable <code>new_json</code>. This can be understood as default values.</p>
  
  <pre><code>{
    "producer": {
       ...
    }
    consumers": {
      ...
    }
  } 
  </code></pre>
  
  <p>Then read the session of overrides, if the environment is <code>prod</code>, it will override the value in related keys.</p>
  
  <p>I wrote the <code>forEach</code> codes to read each key in <code>overrides</code>, then I need confirm the key is list or map, then go the end of the part, replace the same key in <code>new_json</code>. </p>
  
  <pre><code>const json = JSON.parse(template)
  
  if ({}.hasOwnProperty.call(overrides, environment)) {
    const env = overrides[environment];
  
    Object.keys(env).forEach((key){
        ...
    }
  }
  </code></pre>
  
  <p>The sample json is a simple one. The real json has several hundred lines. So go through each key is not efficient method.</p>
  
  <p>Are there any quick/smart ways to overrides any keys in overrides to <code>new_json</code> directly?</p>
  
  <h2>Update #1</h2>
  
  <p>With <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign" rel="nofollow noreferrer">Object.assign()</a>, I still need go though each key, otherwise, I got less keys.</p>
  
  <p>For example, with below code, I got less in list of <code>subscriptions</code>. </p>
  
  <pre><code>$ 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
      }
    ]
  }
  </code></pre>
  
  <h2>Update #2</h2>
  
  <p>Thanks to point me to <a href="https://lodash.com/docs/4.17.11#defaultsDeep" rel="nofollow noreferrer">lodash.defaultsDeep</a>, but when merge the maps in list, it has to be one to one matched in same position. </p>
  
  <p>Use the exist as sample, if I adjust <code>overrides</code> a little bit, the subscriptions' first list, name is changed from <code>app_name1</code> to <code>app_name2</code></p>
  
  <pre><code>"overrides": {
      "prod": {
        "producer": {
          "shards": 2,
          "subscriptions": [
            {
              "name": "app_name2_{{ ENVIRONMENT }}_consumer",
              "account_id": "123456789012",
              "active": false
            }
          ]
        }
    }
  </code></pre>
  
  <p>The result will be: </p>
  
  <pre><code>{ 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' }
  </code></pre>
  
  <p>There are two <code>app_name2</code> now.</p>