将变量注入JSON配置文件

时间:2018-01-25 14:00:22

标签: json node.js go config inject

我们有一个AWS Lambda函数,可以动态地为我们的工程师构建测试环境,以便通过GitHub拉取请求测试他们的代码。

使用GitHub webhooks调用此Lambda函数,Github对所有为该特定产品配置测试环境所需的信息进行POST。

目前,AWS Lambda函数已经过硬编码,可以解析POST数据并构建测试环境。但是,随着测试产品范围的增加和测试环境的范围变得更加多样化,我们希望摆脱硬编码方法;为了便于管理。

我希望能够做的是加载配置文件,最好是用JSON加载,并将GitHub POST数据中的一些数据应用到配置文件中,基本上将数据注入JSON配置。

我不知道如何处理这个问题。我在这里看到一个问题想要做类似的事情,但在Java中: Inject dynamically generated data into JSON

最初我们的Lambda函数是用Node.js编写的,但我们已经开始转向Go - 主要是因为这是一个有趣的新挑战。如果在Node.js中有解决方案,我会接受,但如果在Go中有可用的解决方案,那将更可取。

编辑:

配置文件和GitHub POST数据有两种不同的结构。

GitHub POST数据 (严重剥离)

{
 "action": "opened",
  "number": 89,
  "pull_request": {
    "url": "https://api.github.com/repos/Owner/ExampleRepository/pulls/89",
    "head": {
      "repo": {
        "id": 123454678,
         "name": "ExampleRepository"
        }
      }
  }
}

示例配置文件 (也已删除)

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": [GitHub Post data].pull_request.url,
  "Resources": {
      "ElasticBeanstalk": {
         "Type": "AWS::ElasticBeanstalk::Environment",
         "Properties": {
             "ApplicationName": [GitHub Post data].pull_request.head.repo + [GitHub Post data].number,
             "Description": [GitHub Post data].pull_request.url
          }
     }
  }
}

配置文件和GitHub POST数据都比这复杂得多。此外,配置文件将多次引用POST数据的各个部分,有时需要连接多个值。

3 个答案:

答案 0 :(得分:2)

尝试文本操作JSON文本可能容易出错(考虑转义和unicode序列,例如这是有效的JSON:{"a":"\"b"})。将JSON配置解组为Go值,对其执行修改,然后编组为JSON更容易,更安全。

如果已知配置结构,请创建匹配的Go结构以对其进行精确建模。

如果配置结构未知或您不想麻烦它,您可以解组为interface{}类型的值,并对其进行修改。这将更加冗长,因为您必须为每个属性和索引执行类型断言。

为了减轻后者的痛苦,您可以使用第三方库,例如github.com/icza/dyno(披露:我是作者)。

要从POST请求中“合并”现有的配置和数据,请查看以下答案:"Merge" fields two structs of same type

答案 1 :(得分:0)

为什么不使用标准套餐? os包具有ExpandEnv,以使用环境变量值扩展给定字符串中的${VARNAME}$VARNAME样式子字符串。只需将值作为环境值传递,读取文件并执行:

replacedVars := os.ExpandEnv(fContents)

检查os.ExpandEnv docs

基本上,我写的是:

package main

import (
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    fname = "foobar.json" // wherever this comes from
    buf, err := ioutil.ReadFile(fname)
    if err != nil {
        fmt.Printf("Failed to read file %s - %+v", fname, err)
        return
    }
    conf := os.ExpandEnv(string(buf))
    // do whatever you need to do with conf string...
}

答案 2 :(得分:0)

我感谢所有回复,每一回应都帮助我进一步增加了对Go的了解。

为我解决这个问题的最好方法是使用文本/模板库并将JSON配置创建为文本模板,这样我就可以轻松地应用GitHub发布请求中的变量。

https://golang.org/pkg/text/template/