解码JSON值,可以是字符串或数字

When I make an HTTP call to a REST API I may get the JSON value count back as a Number or String. I'ld like to marshal it to be an integer in either case. How can I deal with this in Go?.

Use the "string" field tag option to specify that strings should be converted to numbers. The documentation for the option is:

The "string" option signals that a field is stored as JSON inside a JSON-encoded string. It applies only to fields of string, floating point, integer, or boolean types. This extra level of encoding is sometimes used when communicating with JavaScript programs:

Here's an example use:

type S struct {
    Count int `json:"count,string"`
}

playground example

If the JSON value can be number or string, then unmarshal to interface{} and convert to int after unmarshaling:

Count interface{} `json:"count,string"`

Use this function to convert the interface{} value to an int:

func getInt(v interface{}) (int, error) {
  switch v := v.(type) {
  case float64:
    return int(v), nil
  case string:
    c, err := strconv.Atoi(v)
    if err != nil {
       return 0, err
    }
  default:
    return 0, fmt.Errorf("conversion to int from %T not supported", v)
  }
}
// Format of your expected request
type request struct {
    ACTIVE    string `json:"active"`
    CATEGORY  string `json:"category"`
}

// struct to read JSON input
var myReq request 

// Decode the received JSON request to struct
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&myReq)
  if err != nil {
  log.Println( err)
// Handler for invalid JSON received or if you want to decode the request using another struct with int.
  return
}
defer r.Body.Close()

// Convert string to int
numActive, err = strconv.Atoi(myReq.ACTIVE)
if err != nil {
  log.Println(err) 
// Handler for invalid int received
  return
}

// Convert string to int    
numCategory, err = strconv.Atoi(myReq.CATEGORY)
if err != nil {
  log.Println(err)
// Handler for invalid int received
  return
}

I had the same problem with a list of values where the values were string or struct. The solution I'm using is to create a helper struct with fields of expected types and parse value into the correct field.

type Flag struct {
    ID   string `json:"id"`
    Type string `json:"type"`
}

type FlagOrString struct {
    Flag   *Flag
    String *string
}

func (f *FlagOrString) UnmarshalJSON(b []byte) error {
    start := []byte("\"")
    for idx := range start {
        if b[idx] != start[idx] {
            return json.Unmarshal(b, &f.Flag)
        }
    }
    return json.Unmarshal(b, &f.String)
}

var MainStruct struct {
    Vals []FlagOrString
}

Custom Unmarshaller simplifies a code. Personally I prefer this over interface{} as it explicitly states what a developer expects.