Go를 사용하여 빈 구조체를 JSON으로 마샬링하지 않는 방법은 무엇입니까?
다음과 같은 구조체가 있습니다.
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
그러나 MyStruct의 인스턴스가 완전히 비어 있어도 (즉, 모든 값이 기본값 임) 다음과 같이 직렬화됩니다.
"data":{}
인코딩 / json 문서에 "빈"필드가 다음과 같이 지정되어 있음을 알고 있습니다.
false, 0, 모든 nil 포인터 또는 인터페이스 값 및 길이가 0 인 모든 배열, 슬라이스, 맵 또는 문자열
그러나 모든 비어있는 / 기본값을 가진 구조체는 고려하지 않습니다. 모든 필드에도로 태그가 지정되어 omitempty
있지만 아무 효과가 없습니다.
빈 구조체 인 필드를 마샬링 하지 않도록 JSON 패키지를 얻으려면 어떻게 해야합니까?
오! 쉬운 수정 : "모든 nil 포인터" -구조체를 포인터로 만듭니다.
고치다:
type Result struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
를 주목하라 *MyStruct
- 나는를 만들 때 MyStruct
지금, 나는 단순히 참조하여 수행 :
myStruct := &MyStruct{ /* values */ }
이제 "빈" MyStruct
은 더 이상 원하는대로 JSON으로 마샬링되지 않습니다.
@chakrit 코멘트에서 언급 한 바와 같이, 당신은 구현하여 작업이 얻을 수 없습니다 json.Marshaler
에 MyStruct
, 그리고 사용 그것은 더 많은 작업을 할 수있는 모든 구조체에서 사용자 정의 JSON 마샬링 기능을 구현. 추가 작업의 가치가 있는지 또는 JSON에서 빈 구조체로 살 준비가되었는지 여부에 대한 사용 사례에 따라 다르지만 여기에 적용한 패턴이 있습니다 Result
.
type Result struct {
Data MyStruct
Status string
Reason string
}
func (r Result) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}{
Data: &r.Data,
Status: r.Status,
Reason: r.Reason,
})
}
func (r *Result) UnmarshalJSON(b []byte) error {
decoded := new(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
})
err := json.Unmarshal(b, decoded)
if err == nil {
r.Data = decoded.Data
r.Status = decoded.Status
r.Reason = decoded.Reason
}
return err
}
If you have huge structs with many fields this can become tedious, especially changing a struct's implementation later, but short of rewriting the whole json
package to suit your needs (not a good idea), this is pretty much the only way I can think of getting this done while still keeping a non-pointer MyStruct
in there.
Also, you don't have to use inline structs, you can create named ones. I use LiteIDE with code completion though, so I prefer inline to avoid clutter.
Data
is an initialized struct, so it isn't considered empty because encoding/json
only looks at the immediate value, not the fields inside the struct.
Unfortunately returning nil
from json.Marhsler
currently doesn't work:
func (_ MyStruct) MarshalJSON() ([]byte, error) {
if empty {
return nil, nil // unexpected end of JSON input
}
// ...
}
You could give Result
a marshaler as well, but it's not worth the effort.
The only option, as Matt suggests, is to make Data
a pointer and set the value to nil
.
There is an outstanding Golang proposal for this feature which has been active for over 4 years, so at this point, it is safe to assume that it will not make it into the standard library anytime soon. As @Matt pointed out, the traditional approach is to convert the structs to pointers-to-structs. If this approach is infeasible (or impractical), then an alternative is to use an alternate json encoder which does support omitting zero value structs.
I created a mirror of the Golang json library (clarketm/json) with added support for omitting zero value structs when the omitempty
tag is applied. This library detects zeroness in a similar manner to the popular YAML encoder go-yaml by recursively checking the public struct fields.
e.g.
$ go get -u "github.com/clarketm/json"
import (
"fmt"
"github.com/clarketm/json" // drop-in replacement for `encoding/json`
)
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
j, _ := json.Marshal(&Result{
Status: "204",
Reason: "No Content",
})
fmt.Println(string(j))
// Note: `data` is omitted from the resultant json.
{
"status": "204"
"reason": "No Content"
}
참고URL : https://stackoverflow.com/questions/18088294/how-to-not-marshal-an-empty-struct-into-json-with-go
'developer tip' 카테고리의 다른 글
유니 코드 지원을위한 Java 정규식? (0) | 2020.11.11 |
---|---|
Composer에서 종속성 업데이트가 그렇게 느린 이유는 무엇입니까? (0) | 2020.11.11 |
WhatsApp에서 링크의 썸네일 표시 || (0) | 2020.11.11 |
NVM을 사용하여 기본 노드 버전을 어떻게 설정할 수 있습니까? (0) | 2020.11.11 |
순서를 유지하면서 정렬 된 목록을 데이터베이스에 저장하는 가장 좋은 방법 (0) | 2020.11.11 |