【问题标题】:Dynamic struct definition动态结构定义
【发布时间】:2020-09-29 19:30:38
【问题描述】:

我有一个用例,我将一些 json 文件转换为 Go 结构。我有以下文档结构

{
    
    "contentVersion": "1.0.0.0",

    "paths" : [
      {
        "ParameterReference": "someValue",
      },
      {
        "ParameterReference": "someOtherValue",
      }
    ],
    "parameters": {
        "label": { "value": "label" },
        "domainName": { "value": "domain" },
        "servicePackageLink": { "value": "bin\\test.cspkg" },
        "pfxContent": { "value": "SampleCert.Content" },
        "sampleCertThumbprint": {"value": "SampleCert.Thumbprint"},
        "anotherSampleCertContent":{ "value" : "AnotherSampleCert.Content" },
        "anotherSampleCertThumbprint": {"value": "AnotherSampleCert.Thumbprint"}
    },
    "secrets" :[
      {
        "TargetReference":"SERviceConfiGURatiONLiNK",
        "Replacements":
        {
          "__Secret_Sample__" :
          {
            "SecretId":"secretID",
            "EncryptWith" :"encryptWithValue"
          },
          "__Another_Secret_Sample__" :
          {
            "SecretId":"anotherSecretValue",
            "EncryptWith" :"anotherEncryptWithValue"
          },
          "__Storage_ConnectionString__" : "someConnectionString"
        },
      },
      {
        "TargetReference":"None",
        "Certificates":[
          {
            "Name":"AnotherSampleCert",
            "ContentReference" : "contentReference"
          }
        ]
      }
    ]
}
  

我面临的问题是 json 没有固定的架构,例如。

  1. 如果您检查parameters 对象,特别是名称为sampleCertSchema 的条目,在我的用例中,用户可以提供从0 到N 的任意数量的此类____CertSchemas 值. 所以,参数字段也可以如下
"parameters": {
        "label": { "value": "label" },
        "domainName": { "value": "domain" },
        "servicePackageLink": { "value": "bin\\test.cspkg" },
        "pfxContent": { "value": "SampleCert.Content" }
    },
  1. 另一个例子是secrets.Replacements 对象。各个替换对象的名称可以是正则表达式/^[ A-Za-z0-9_@./#&+-]*$/ 格式的任何内容,这也是一个动态数组,如第一点中提到的parameters 字段。因此,另一个可能的值可以是
"Replacements":
        {
          "__Secret_Sample__" :
          {
            "SecretId":"secretID",
            "EncryptWith" :"encryptWithValue"
          },
          "__Storage_ConnectionString__" : "someConnectionString"
        },
  1. 使用字段paths,我可以是一个对象数组或只是一个字符串数组。例如,除了上面的格式,还可以是
"paths": [
        "servicePackageLink",
        "serviceConfigurationLink"
    ]

使用 C#/Java,我可以使用 Object 类创建一个文档来处理这些未知的动态对象名称和条目。使用 Go,我尝试定义以下结构

type pathDefinition struct {
    ParameterReference     string `json:"parameterReference"`
    EnableHealthDimensions bool   `json:"enableHealthDimensions"`
}

type parameterValue struct {
    Values map[string]interface{}
}

type replacements struct {
    SecretValueMap map[string]interface{} `json:"secretValueMap"`
}

type resourceCertificate struct {
    Name              string `json:"name"`
    ContentReference  string `json:"contentReference"`
    PasswordReference string `json:"passwordReference"`
    Content           string `json:"content"`
    Password          string `json:"password"`
    Thumbprint        string `json:"thumbprint"`
    SubjectName       string `json:"subjectName"`
}

type resourceSecrets struct {
    TargetReference string              `json:"targetReference"`
    Replacements    replacements        `json:"replacements"`
    Certificates    resourceCertificate `json:"certificates"`
}

type ResouceParameters struct {
    Schema         string `json:"$schema"`
    ContentVersion string `json:"contentVersion"`
    Paths          interface{}
    Parameters     map[string]parameterValue `json:"parameters"`
    Secrets        resourceSecrets           `json:"secrets"`
    Others         map[string]interface{}    `json:"others"`
}

使用此定义,我无法将文件数据解组到 ResouceParameters 结构变量中。以下是我解组的方式

    file, _ := os.Open("path/to/parameters.json")
    defer file.Close()

    byteValue, _ := ioutil.ReadAll(file)

    fileData := new(ResouceParameters)

    err := json.Unmarshal([]byte(byteValue), &fileData)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(fileData)

这将打印一个空结构。我的问题是,我应该如何在 Go 中定义一个结构,以便它能够加载带有 non 预定义条目的 json。使用 java/C# 我可以使用 Object 类并创建一个文档,但我无法理解使用 Go 来执行此操作。

【问题讨论】:

  • 您应该会遇到解组错误,因为参数将无法解组到您拥有的结构。使用map[string]interface{} 作为参数。另外,您不需要new,只需声明变量即可。
  • @mkopriva 感谢您提供的示例,它让我了解了该做什么。我想你错过了我对paths 字段问题的编辑
  • @htyagi 路径的作用与Secret 相同,实现解组器并根据第一个字节决定如何解组单个元素。
  • @mkopriva 是的,我尝试做同样的事情,当路径是对象数组时它会传递,但当它是字符串数组时会失败play.golang.org/p/0dFb0bfL-6Z

标签: json go struct


【解决方案1】:

go 中的等价物是 interface{},即空接口。例如,看看这个答案:Unmarshaling Into an Interface{} and Then Performing Type Assertion

一旦您知道要搜索的字词,您应该能够在需要时搜索更详细的内容。

【讨论】:

    【解决方案2】:

    @mkopriva 评论是我一直在寻找的东西。 https://play.golang.org/p/SOsKGCZtlxk

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2011-09-05
      相关资源
      最近更新 更多