douhezhan5348 2018-04-18 13:41
浏览 334
已采纳

在Go JSON封送中嵌入map [string] string,无需额外的JSON属性(内联)

Is there a way to embed a map[string]string inline?

What I got is:

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

What I mean with embed or inline would be an expected result like this:

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

This is my code... I load the information from a yaml file an want to return the JSON in the desired format from above:

This is my yaml:

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

This is my Go code:

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))

}

This obviously does work:

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

but I was hoping that something similar exists to embed the tags map without the JSON property tags.

  • 写回答

1条回答 默认 最新

  • dougou1127 2018-04-18 14:06
    关注

    There is no native way to "flatten" fields, but you can do it manually with a series of Marshal/Unmarshal steps (error handling omitted for brevity):

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100