首页 > 解决方案 > 动态结构定义

问题描述

我有一个用例,我将一些 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. 使用 field 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 中定义一个结构,以便它能够加载一个带有预定义条目的 json。使用 java/C# 我可以使用Object该类并创建一个文档,但我无法理解使用 Go 来执行此操作。

标签: jsongostruct

解决方案


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

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


推荐阅读