最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I convert an environment variable to an object in JS? - Stack Overflow

programmeradmin4浏览0评论

I'm trying to convert an environment variable into an object of values for configuration in JavaScript but I don't know the best way to achieve this.

The idea would be to output SAMPLE_ENV_VAR=value as:

{
    sample: {
        env: {
            var: value
        }
    }
}

What I have so far:

const _ = require('lodash');
const process = require('process');

_.each(process.env, (value, key) => {
    key = key.toLowerCase().split('_');
    // Convert to object here
}

I'm trying to convert an environment variable into an object of values for configuration in JavaScript but I don't know the best way to achieve this.

The idea would be to output SAMPLE_ENV_VAR=value as:

{
    sample: {
        env: {
            var: value
        }
    }
}

What I have so far:

const _ = require('lodash');
const process = require('process');

_.each(process.env, (value, key) => {
    key = key.toLowerCase().split('_');
    // Convert to object here
}
Share Improve this question asked Aug 29, 2016 at 19:41 Adam JohnsonAdam Johnson 1151 silver badge7 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 3

Here's a more plete solution based on yours:

const _ = require('lodash');
const result = {};

// We'll take the following as an example:
// process.env = { HELLO_WORLD_HI: 5 }
// We'll expect the following output:
// result = { hello: { world: { hi: 5 } } }
_.each(process.env, (value, key) => {
    // We'll separate each key every underscore.
    // In simple terms, this will turn:
    // "HELLLO_WORLD_HI" -> ['HELLO', 'WORLD', 'HI']
    const keys = key.toLowerCase().split('_');

    // We'll start on the top-level object
    let current = result;

    // We'll assign here the current "key" we're iterating on
    // It will have the values:
    // 'hello' (1st loop), 'world' (2nd), and 'hi' (last)
    let currentKey;

    // We'll iterate on every key. Moreover, we'll
    // remove every key (starting from the first one: 'HELLO')
    // and assign the removed key as our "currentKey".
    // currentKey = 'hello', keys = ['world', 'hi']
    // currentKey = 'world', keys = ['hi'], and so on..
    while ( (currentKey = keys.shift()) ) {
        // If we still have any keys to nest,
        if ( keys.length ) {
          // We'll assign that object property with an object value
          // result =// { HELLO: {} }
          current[currentKey] = {};

          // And then move inside that object so
          // could nest for the next loop
          // 1st loop: { HELLO: { /*We're here*/ } }
          // 2nd loop: { HELLO: { WORLD: { /*We're here*/ } } }
          // 3rd loop: { HELLO: { WORLD: { HI : { /*We're here*/ } } } }
          current = current[currentKey];
        } else {
          // Lastly, when we no longer have any key to nest
          // e.g., we're past the third loop in our example
          current[currentKey] = process.env[key]
        }
    }
});

console.log(result);

To simply put:

  • We'll loop through every environment variable (from process.env)
  • Split the key name with an underscore, and, again, loop each key (['HELLO', 'WORLD', 'HI'])
  • Assign it to an object ({ hello: {} } -> { hello: { world: {} } } -> { hello: world: { hi: ? } } })
  • When we no longer have any keys left, assign it to the actual value ({ hello: { world: { hi: 5 } } })

Funnily enough, I just finished code for this last night for a personal project. What I ended up using is not ideal, but is working for me:

export function keyReducer(
  src: any,
  out: any,
  key: string,
  pre: string,
  del: string
): ConfigScope {
  const path = key.toLowerCase().split(del);
  if (path[0] === pre.toLowerCase()) {
    path.shift();
  }

  if (path.length === 1) { // single element path
    const [head] = path;
    out[head] = src[key];
  } else {
    const tail = path.pop();
    const target = path.reduce((parent: any, next: string) => {
      if (parent[next]) {
        return parent[next];
      } else {
        return (parent[next] = <ConfigScope>{});
      }
    }, out);
    target[tail] = src[key];
  }
  return out;
}

static fromEnv(env: Environment, {prefix = 'ABC', delimiter = '_'} = {}) {
  const data: ConfigScope = Object.keys(env).filter(key => {
    return StringUtils.startsWith(key, prefix);
  }).reduce((out, key) => {
    return keyReducer(env, out, key, prefix, '_');
  }, <ConfigScope>{});
  return new Config(data);
}

(with TypeScript type annotations)

The idea here is to split each key, create the target objects on the way down, then set the final value.

This is my quick take at it:

var object = {}; // the object to store the value in 
var name = "SAMPLE_ENV_VAR"; // the environment variable key
var value = "value"; // the value of the environment variable

// helper function to automatically create an inner object if none exists
function getOrCreateInnerObj(obj, name) {
  if (!obj.hasOwnProperty()) {
    obj[name] = {};
  }
  return obj[name];
}

// an array of the individual parts (e.g. ["sample", "env", "var"])
var keyParts = name.toLowerCase().split("_");

// innerObj will contain the second to last element object in the tree based on the array of keys
var innerObj = getOrCreateInnerObj(object, keyParts[0]);
for (var i = 1; i < keyParts.length - 1; i++) {
  innerObj = getOrCreateInnerObj(innerObj, keyParts[i]);
}

// set the value itself
innerObj[keyParts[keyParts.length - 1]] = value;

$("body").html(JSON.stringify(object));

The gist of it is, for all but the last element in the array of key parts, you get or create an object in the current parent object for that key, and once you've repeated this for all but the last key, you'll have the second-to-last inner object, which you can then set the value on.

Edit: Working example

Edit 2: Here is a much cleaner example that uses a little bit of recursion to acplish the same thing

const basic = {};
let current;
`YOUR_VARIABLE_NAME`
  .split(`_`)
  .forEach((item, index, array) => {
    if(index === 0) {
      return current = basic[item] = {};
    }
    if(index === array.length - 1) {
      return current[item] = process.env.HE_LO_NA;
    }
    current = current[item] = {};
});

console.log(require('util').inspect(basic, {depth: 10}));
const _ = require('lodash');
const process = require('process');

const result = Object.entries(process.env).reduce((acc, [key, value]) => {
    _.set(acc, key.toLowerCase().replace('_', '.'), value);
    return acc;
}, {})
发布评论

评论列表(0)

  1. 暂无评论