Reputation: 6882
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
.
Upvotes: 1
Views: 4048
Reputation: 31721
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
Upvotes: 6