Go:JSON编组嵌套结构;错误地忽略外部字段

Go:JSON编组嵌套结构;错误地忽略外部字段,json,go,marshalling,Json,Go,Marshalling,我正在尝试封送嵌套结构。请看一个不起作用的示例(我无法在Go游乐场中导入“compute”和“pretty”,但我已经重新创建了测试逻辑并粘贴了输出) 主程序包 进口( “编码/json” “fmt” “github.com/kylelemons/godebug/pretty” compute“google.golang.org/api/compute/v1” ) 类型CreateInstance结构{ 计算实例 //要为实例设置的其他元数据。 元数据映射[string]string`json:

我正在尝试封送嵌套结构。请看一个不起作用的示例(我无法在Go游乐场中导入“compute”和“pretty”,但我已经重新创建了测试逻辑并粘贴了输出)

主程序包
进口(
“编码/json”
“fmt”
“github.com/kylelemons/godebug/pretty”
compute“google.golang.org/api/compute/v1”
)
类型CreateInstance结构{
计算实例
//要为实例设置的其他元数据。
元数据映射[string]string`json:“元数据,省略为空”`
//OAuth2作用域来提供实例。如果未指定
// https://www.googleapis.com/auth/devstorage.read_only 将添加。
作用域[]字符串`json:,省略为空“`
//StartupScript是此步骤中使用的启动脚本的源路径。
//这将自动映射到相应的元数据密钥。
StartupScript字符串`json:,省略为空'`
//要在中创建实例的项目将覆盖工作流项目。
项目字符串`json:“,省略为空”`
//要在其中创建实例的区域,将覆盖工作流区域。
区域字符串`json:“,省略为空”`
//是否应在工作流结束后清理此资源?
夜光布尔
//我们应该使用用户提供的引用名称作为实际的资源名称吗?
正名布尔
//Daisy内部已知的磁盘名称。
daisyName字符串
}
func main(){
ci:=.CreateInstance还有两个没有JSON标记的bool字段,ExactName和NoCleanup


当我试图封送CreateInstance时,ExactName和NoCleanup被省略,不管它们是真是假。

a
compute.Instance
是一个
json.Marshaler
,因此通过嵌入该类型,本质上就是从
compute.Instance
中提供
MarshalJSON
方法,这当然是我的sn不会输出
CreateInstance
结构中的任何字段

您可以定义自己的
MarshalJSON
方法,并尝试手动封送
实例
,或将其重新分配给将使用默认json输出的新类型,但API可能依赖内部
MarshalJSON
行为,因此不能保证与当前或未来版本兼容


最好避免嵌入json封送处理的类型,因为这样很容易产生令人困惑的错误。我会尝试以不同的方式组合它们。

a
compute.Instance
是一个
json.Marshaler
,因此通过嵌入该类型,您实质上是为
CreateInstance
提供了
封送json
compute.Instance
中的方法,它当然不会输出
CreateInstance
结构中的任何字段

您可以定义自己的
MarshalJSON
方法,并尝试手动封送
实例
,或将其重新分配给将使用默认json输出的新类型,但API可能依赖内部
MarshalJSON
行为,因此不能保证与当前或未来版本兼容


最好避免为json封送嵌入类型,因为这样很容易产生令人困惑的错误。我会尝试以不同的方式组合它们。

这里有一个近似值:它按预期工作。封送缩进是否返回错误?近似值很好。不,MashalIndent不会返回错误。因此,我很抱歉当前正在传递一个*CreateInstance。当我撤销它时,它会工作。不,这更像是正在发生的事情:这里有一个近似值:它按预期工作。MarshalIndent是否返回错误?很好的近似值。不,MashalIndent不会返回错误。因此,我当前正在传递一个*CreateInstance。当我撤销它时,它会工作。不,这是is更像是正在发生的事情:嘿,谢谢!不幸的是,试图“以不同的方式编写它们”这有点困难,因为我们想向用户公开JSON配置模式。嵌入比JSON配置中的内部compute.Instance实例或指针更好,因为内部compute.Instance需要一个嵌套对象。嘿,谢谢!不幸的是,尝试“以不同的方式组合它们”这有点困难,因为我们想向用户公开JSON配置模式。嵌入比JSON配置中的内部compute.Instance实例或指针更好,因为内部compute.Instance需要嵌套对象。
package main

import (
    "encoding/json"
    "fmt"

    "github.com/kylelemons/godebug/pretty"
    compute "google.golang.org/api/compute/v1"
)

type CreateInstance struct {
    compute.Instance

    // Additional metadata to set for the instance.
    Metadata map[string]string `json:"metadata,omitempty"`
    // OAuth2 scopes to give the instance. If none are specified
    // https://www.googleapis.com/auth/devstorage.read_only will be added.
    Scopes []string `json:",omitempty"`

    // StartupScript is the Sources path to a startup script to use in this step.
    // This will be automatically mapped to the appropriate metadata key.
    StartupScript string `json:",omitempty"`
    // Project to create the instance in, overrides workflow Project.
    Project string `json:",omitempty"`
    // Zone to create the instance in, overrides workflow Zone.
    Zone string `json:",omitempty"`
    // Should this resource be cleaned up after the workflow?
    NoCleanup bool
    // Should we use the user-provided reference name as the actual resource name?
    ExactName bool

    // The name of the disk as known internally to Daisy.
    daisyName string
}

func main() {
    ci := <a *CreateInstance part of a larger data structure>
    j, _ := json.MarshalIndent(ci, "", "  ")
    fmt.Println(string(j))
    pretty.Print(ci)  # Pretty prints the struct.
}


##### OUTPUT #####
{
  "disks": [
    {
      "source": "disk"
    }
  ],
  "machineType": "${machine_type}",
  "name": "${instance_name}"
}
{Instance:      {CanIpForward:      false,
                 CpuPlatform:       "",
                 CreationTimestamp: "",
                 Description:       "",
                 Disks:             [{AutoDelete:        false,
                                      Boot:              false,
                                      DeviceName:        "",
                                      DiskEncryptionKey: nil,
                                      Index:             0,
                                      InitializeParams:  nil,
                                      Interface:         "",
                                      Kind:              "",
                                      Licenses:          [],
                                      Mode:              "",
                                      Source:            "disk",
                                      Type:              "",
                                      ForceSendFields:   [],
                                      NullFields:        []}],
                 Id:                0,
                 Kind:              "",
                 MachineType:       "${machine_type}",
                 Metadata:          nil,
                 Name:              "${instance_name}",
                 NetworkInterfaces: [],
                 Scheduling:        nil,
                 SelfLink:          "",
                 ServiceAccounts:   [],
                 Status:            "",
                 StatusMessage:     "",
                 Tags:              nil,
                 Zone:              "",
                 ServerResponse:    {HTTPStatusCode: 0,
                                     Header:         {}},
                 ForceSendFields:   [],
                 NullFields:        []},
 Metadata:      {},
 Scopes:        [],
 StartupScript: "",
 Project:       "",
 Zone:          "",
 NoCleanup:     false,
 ExactName:     false}