在Go JSON编组中嵌入map [string]字符串,没有额外的JSON属性(内联)

时间:2018-04-18 13:41:31

标签: json go marshalling

有没有办法嵌入map[string]string内联?

我得到的是:

{
    "title": "hello world",
    "body": "this is a hello world post",
    "tags": {
        "hello": "world"
    }
}

我对embed或inline的意思是这样的预期结果:

    {
    "title": "hello world",
    "body": "this is a hello world post",
    "hello": "world"
}

这是我的代码...我从yaml文件中加载信息,想要从上面以所需的格式返回JSON:

这是我的名字:

title: hello world
body: this is a hello world post
tags:
  hello: world

这是我的Go代码:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"

    "gopkg.in/yaml.v2"
)

type Post struct {
    Title string            `yaml:"title" json:"title"`
    Body  string            `yaml:"body" json:"body"`
    Tags  map[string]string `yaml:"tags" json:",inline"`
}

func main() {

    yamlBytes, err := ioutil.ReadFile("config.yaml")
    if err != nil {
        panic(err)
    }

    var post Post

    yaml.Unmarshal(yamlBytes, &post)

    jsonBytes, err := json.Marshal(post)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(jsonBytes))

}

这显然有效:

Tags map[string]string `yaml:"tags" json:",inline"`

但我希望在没有JSON属性tags的情况下嵌入tags地图存在类似的东西。

1 个答案:

答案 0 :(得分:3)

没有本地方法来“展平”字段,但您可以使用一系列Marshal / Unmarshal步骤手动完成(为简洁省略了错误处理):

type Post struct {
    Title string            `yaml:"title" json:"title"`
    Body  string            `yaml:"body" json:"body"`
    Tags  map[string]string `yaml:"tags" json:"-"` // handled by Post.MarshalJSON
}

func (p Post) MarshalJSON() ([]byte, error) {
    // Turn p into a map
    type Post_ Post // prevent recursion
    b, _ := json.Marshal(Post_(p))

    var m map[string]json.RawMessage
    _ = json.Unmarshal(b, &m)

    // Add tags to the map, possibly overriding struct fields
    for k, v := range p.Tags {
        // if overriding struct fields is not acceptable:
        // if _, ok := m[k]; ok { continue }
        b, _ = json.Marshal(v)
        m[k] = b
    }

    return json.Marshal(m)
}

https://play.golang.org/p/Xvu2VYeZFGh