go - 在JSON响应中,Golang从结构中删除字段或者隐藏它们

我创建了一个API,被调用时会执行查询,创建一个struct的实例,然后将该结构编码为JSON再发送回调用方,我想让调用者能够选择想要返回的特定字段。

是否有什么方法从结构中删除字段? 或者至少将它们动态地隐藏在JSON响应中?

我使用的较小版本如下:


type SearchResult struct {
 Date string `json:"date"`
 IdCompany int `json:"idCompany"`
 Company string `json:"company"`
 IdIndustry interface{} `json:"idIndustry"`
 Industry string `json:"industry"`
 IdContinent interface{} `json:"idContinent"`
 Continent string `json:"continent"`
 IdCountry interface{} `json:"idCountry"`
 Country string `json:"country"`
 IdState interface{} `json:"idState"`
 State string `json:"state"`
 IdCity interface{} `json:"idCity"`
 City string `json:"city"`
} //SearchResult

type SearchResults struct {
 NumberResults int `json:"numberResults"`
 Results []SearchResult `json:"results"`
} //type SearchResults

然后编码并输出响应:


err := json.NewEncoder(c.ResponseWriter).Encode(&msg)

时间:

编辑:我注意到了一些 downvotes,并再次查看了这个 q& 。 大多数人似乎小姐,op要求字段动态根据caller-provided选择字段的列表。 你不能使用 statically-defined json结构标记进行这里操作。

如果你想要的是总是 json-encode跳过一个字段,那么当然( 也不注意,这是要求如果你的字段是unexported——这些字段总是忽视了json编码器) json:"-" 忽略使用字段。 但这并不是操作的问题。

要在 json:"-" 回答中引用评论:

这个答案是 [the json:"-" answer] 大多数人最终从搜索想要的,但这并不是问题的答案。


我将使用映射 [string] 接口 {},而不是在这种情况下使用结构。 你可以通过调用映射中的delete 来删除字段,以便删除字段。

也就是说,如果你不能在第一个位置查询请求的字段,。

使用json :“—”`


// Field is ignored by this package.
Field int `json:"-"`

// Field appears in JSON as key"myName".
Field int `json:"myName"`

// Field appears in JSON as key"myName" and
// the field is omitted from the object if its value is empty,
// as defined above.
Field int `json:"myName,omitempty"`

// Field appears in JSON as key"Field" (the default), but
// the field is skipped if empty.
// Note the leading comma.
Field int `json:",omitempty"`

文档:http://golang.org/pkg/encoding/json/#Marshal

另一种方法是使用omitempty标记的指针结构,如果指针为零,则不对字段进行编组。

这种方法不需要额外的反射或低效的map使用。

http://play.golang.org/p/JJNa0m2_nw

你可以使用reflect包来选择所需的字段,方法是在字段标记上反射并选择json标记值,定义SearchResults类型上的方法,选择所需字段并将它返回为map[string]interface{},然后将它封送为SearchResults结构本身,下面是你如何定义该方法的例子:


func fieldSet(fields ...string) map[string]bool {
 set := make(map[string]bool, len(fields))
 for _, s := range fields {
 set[s] = true
 }
 return set
}

func (s *SearchResult) SelectFields(fields ...string) map[string]interface{} {
 fs := fieldSet(fields...)
 rt, rv := reflect.TypeOf(*s), reflect.ValueOf(*s)
 out := make(map[string]interface{}, rt.NumField())
 for i := 0; i < rt.NumField(); i++ {
 field := rt.Field(i)
 jsonKey := field.Tag.Get("json")
 if fs[jsonKey] {
 out[jsonKey] = rv.Field(i).Interface()
 }
 }
 return out
}

下面是一个可运行解决方案,演示如何调用此方法: http://play.golang.org/p/1K9xjQRnO8

你可以使用标记属性"omitifempty"或者制作可选的字段指针,并将那些你想要跳过的字段去掉。

这个问题现在有点过时了,但是我发现了相同的问题,它允许从静态结构轻松生成map[string]interface{}

https://github.com/tuvistavie/serializer

...