如何构造JSON,以便我可以使用golang接收int64和字符串?

I have the follow example code:

type Num struct {
    X uint64 `json:"x,string"`
    Y float64 `json:"y,string"`
}

Now, if I run the code

js := []byte(`{"x": "123", "y": "1.23"}`)
var n Num
err := json.Unmarshal(js, &n)

it will parse ok.

But if I change the JSON to

js := []byte(`{"x": 123, "y": 1.23}`)

it returns an error.

The result I can understand.

Now, my problem is how can I make it accept both string and uint64/float64?

You will need to define a custom type that implements the json.Unmarshaler interface in such a way that the value can be either a string or a plain number.

The example below shows how to do it for a single type (uint64); you will need to repeat the pattern for any other numerical types (Go Playground):

type Uint64 uint64

type Num struct {
  X Uint64 `json:"x"`
}

func (u *Uint64) UnmarshalJSON(bs []byte) error {
  str := string(bs) // Parse plain numbers directly.
  if bs[0] == '"' && bs[len(bs)-1] == '"' {
    // Unwrap the quotes from string numbers.
    str = string(bs[1 : len(bs)-1])
  }
  x, err := strconv.ParseUint(str, 10, 64)
  if err != nil {
    return err
  }
  *u = Uint64(x)
  return nil
}

func main() {
  ss := []string{`{"x":"123"}`, `{"x":123}`}
  var n Num

  for _, s := range ss {
    err := json.Unmarshal([]byte(s), &n)
    fmt.Printf("OK: s=%-11s  n=%#v  err=%v
", s, n, err)
  }
  // OK: s={"x":"123"}  n=main.Num{X:0x7b}  err=<nil>
  // OK: s={"x":123}    n=main.Num{X:0x7b}  err=<nil>
}

Building on @maerics answer, you can defer both cases to the usual json unmarshaler, which feels a bit more robust:

package main

import (
    "encoding/json"
    "errors"
    "fmt"
)

type Uint64 uint64

type Num struct {
    X Uint64 `json:"x"`
}

func (u *Uint64) UnmarshalJSON(bs []byte) error {
    var i uint64
    if err := json.Unmarshal(bs, &i); err == nil {
        *u = Uint64(i)
        return nil
    }
    var s string
    if err := json.Unmarshal(bs, &s); err != nil {
        return errors.New("expected a string or an integer")
    }
    if err := json.Unmarshal([]byte(s), &i); err != nil {
        return err
    }
    *u = Uint64(i)
    return nil
}

func main() {
    ss := []string{`{"x":"123"}`, `{"x":123}`, `{"x":0.12}`}
    var n Num

    for _, s := range ss {
        err := json.Unmarshal([]byte(s), &n)
        fmt.Printf("OK: s=%-11s  n=%#v  err=%v
", s, n, err)
    }
}

which gives

OK: s={"x":"123"}  n=main.Num{X:0x7b}  err=<nil>
OK: s={"x":123}    n=main.Num{X:0x7b}  err=<nil>
OK: s={"x":0.12}   n=main.Num{X:0x7b}  err=expected a string or an integer