英文:
JSON Marshal struct with method return as field
问题
可以将具有方法返回值作为字段的结构进行编组吗?例如,我想要以下JSON:
{
"cards": [1,2,3],
"value": 6,
"size": 3
}
使用以下类型的结构:
type Deck struct {
Cards []int `json:"cards"`
Value func() int `json:"value"`
Size func() int `json:"size"`
}
有人知道吗?
英文:
Is it possible to marshal a struct with method return as field? For example, I want this JSON
{
"cards": [1,2,3],
"value": 6,
"size": 3
}
With this kind of struct
type Deck struct {
Cards []int `json:"cards"`
Value func() int `json:"value"`
Size func() int `json:"size"`
}
Anyone?
答案1
得分: 15
你可以实现一个类似这样的Marshaler,代码示例可以在这里找到:http://play.golang.org/p/ySUFcUOHCZ(或者这里:http://play.golang.org/p/ndwKu-7Y5m)。
package main
import "fmt"
import "encoding/json"
type Deck struct {
Cards []int
}
func (d Deck) Value() int {
value := 0
for _, v := range d.Cards {
value = value + v
}
return value
}
func (d Deck) Size() int {
return len(d.Cards)
}
func (d Deck) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Cards []int `json:"cards"`
Value int `json:"value"`
Size int `json:"size"`
}{
Cards: d.Cards,
Value: d.Value(),
Size: d.Size(),
})
}
func main() {
deck := Deck{
Cards: []int{1, 2, 3},
}
b, r := json.Marshal(deck)
fmt.Println(string(b))
fmt.Println(r)
}
英文:
You can implement a Marshaler like this http://play.golang.org/p/ySUFcUOHCZ (or this http://play.golang.org/p/ndwKu-7Y5m )
<!-- language: lang-go -->
package main
import "fmt"
import "encoding/json"
type Deck struct {
Cards []int
}
func (d Deck) Value() int {
value := 0
for _, v := range d.Cards {
value = value + v
}
return value
}
func (d Deck) Size() int {
return len(d.Cards)
}
func (d Deck) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Cards []int `json:"cards"`
Value int `json:"value"`
Size int `json:"size"`
}{
Cards: d.Cards,
Value: d.Value(),
Size: d.Size(),
})
}
func main() {
deck := Deck{
Cards: []int{1, 2, 3},
}
b, r := json.Marshal(deck)
fmt.Println(string(b))
fmt.Println(r)
}
答案2
得分: 1
你还可以创建一个实现了JSONMarshaler和JSONUnmarshaler接口的函数类型。但是它有一些缺点。
import "fmt"
import "encoding/json"
type IntFunc func() int
func (f IntFunc) MarshalJSON() ([]byte, error) {
return json.Marshal(f())
}
// 注意:在这里你将失去原始函数
func (f *IntFunc) UnmarshalJSON(b []byte) error {
var i int
err := json.Unmarshal(b, &i)
// 你可以添加一个虚拟函数,或者通过不给*f赋值来将其保持为nil
*f = func() int { return i }
return err
}
type Deck struct {
Cards []int `json:"cards"`
Value IntFunc `json:"value"`
Size IntFunc `json:"size"`
}
func main() {
deck := Deck{
Cards: []int{1, 2, 3},
}
deck.Value = ValueOf(&deck)
deck.Size = SizeOf(&deck)
fmt.Printf("Size: %v, Cards: %v, Value: %v\n", deck.Size(), deck.Cards, deck.Value())
deck.Cards = append(deck.Cards, 8)
fmt.Printf("Size: %v, Cards: %v, Value: %v\n", deck.Size(), deck.Cards, deck.Value())
fmt.Println()
b, err := json.Marshal(deck)
fmt.Println("Marshal Error:", err)
fmt.Println("Marshal result:", string(b))
fmt.Println()
var d2 Deck
err = json.Unmarshal([]byte(`{"cards":[1,2,3,8],"value":14,"size":4}`), &d2)
fmt.Println("Unmarshal Error =>", err)
fmt.Printf("Unmarshal Result => Size: %v, Cards: %v, Value: %v\n", d2.Size(), d2.Cards, d2.Value()) // 如果Size()和Value()为nil,可能会抛出错误
}
func SizeOf(d *Deck) IntFunc {
return func() int {
return len(d.Cards)
}
}
func ValueOf(d *Deck) IntFunc {
return func() int {
i := 0
for _, v := range d.Cards {
i += v
}
return i
}
}
英文:
You could also create a function type that implement JSONMarshaler and JSONUnmarshaler. But it has some drawbacks.
import "fmt"
import "encoding/json"
type IntFunc func() int
func (f IntFunc) MarshalJSON() ([]byte, error) {
return json.Marshal(f())
}
// NOTES you'll lose the original function here
func (f *IntFunc) UnmarshalJSON(b []byte) error {
var i int
err := json.Unmarshal(b, &i)
// you could either add dummy function or leave it nil by not assigning *f
*f = func() int { return i }
return err
}
type Deck struct {
Cards []int `json:"cards"`
Value IntFunc `json:"value"`
Size IntFunc `json:"size"`
}
func main() {
deck := Deck{
Cards: []int{1, 2, 3},
}
deck.Value = ValueOf(&deck)
deck.Size = SizeOf(&deck)
fmt.Printf("Size: %v, Cards: %v, Value: %v\n", deck.Size(), deck.Cards, deck.Value())
deck.Cards = append(deck.Cards, 8)
fmt.Printf("Size: %v, Cards: %v, Value: %v\n", deck.Size(), deck.Cards, deck.Value())
fmt.Println()
b, err := json.Marshal(deck)
fmt.Println("Marshal Error:", err)
fmt.Println("Marshal result:", string(b))
fmt.Println()
var d2 Deck
err = json.Unmarshal([]byte(`{"cards":[1,2,3,8],"value":14,"size":4}`), &d2)
fmt.Println("Unmarshal Error =>", err)
fmt.Printf("Unmarshal Result => Size: %v, Cards: %v, Value: %v\n", d2.Size(), d2.Cards, d2.Value()) // could throw error if Size() and Value() is nil
}
func SizeOf(d *Deck) IntFunc {
return func() int {
return len(d.Cards)
}
}
func ValueOf(d *Deck) IntFunc {
return func() int {
i := 0
for _, v := range d.Cards {
i += v
}
return i
}
}
答案3
得分: 0
通常情况下是可以的。你需要使用reflect包,并且基本上编写自己的编组器。
但是使用Go的encoding/json包就不需要了。
英文:
In general, yes. You'd have to use the the reflect package and essentially write your own marshaller.
With Go's encoding/json package, no.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论