【发布时间】: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 没有固定的架构,例如。
- 如果您检查
parameters对象,特别是名称为sampleCertSchema的条目,在我的用例中,用户可以提供从0 到N 的任意数量的此类____CertSchemas 值. 所以,参数字段也可以如下
"parameters": {
"label": { "value": "label" },
"domainName": { "value": "domain" },
"servicePackageLink": { "value": "bin\\test.cspkg" },
"pfxContent": { "value": "SampleCert.Content" }
},
- 另一个例子是
secrets.Replacements对象。各个替换对象的名称可以是正则表达式/^[ A-Za-z0-9_@./#&+-]*$/格式的任何内容,这也是一个动态数组,如第一点中提到的parameters字段。因此,另一个可能的值可以是
"Replacements":
{
"__Secret_Sample__" :
{
"SecretId":"secretID",
"EncryptWith" :"encryptWithValue"
},
"__Storage_ConnectionString__" : "someConnectionString"
},
- 使用字段
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