Go json HTTP请求主体验证模式

Go json HTTP请求主体验证模式,go,Go,我试图理解验证JSON主体的模式 比如说, // I have this struct type Program struct { ProgramKey string `json:"program_key" validate:"required"` Active *bool `json:"active" validate:"required"` } // json request body { "program_key" : "exa

我试图理解验证JSON主体的模式

比如说,

  // I have this struct
  type Program struct {
    ProgramKey string `json:"program_key" validate:"required"`
    Active     *bool     `json:"active" validate:"required"`
  }

  // json request body
  {
    "program_key" : "example-key",
    "active" : false
  }
我想在JSON解码错误出现之前运行请求验证。但不确定这是否是最好的方法

因为每当我解码的时候

   // json request body
   {
    "program_key" : "example-key",
    "active" : "false" // notice the string value here
   }
   json.NewDecoder(r.Body).Decode(&program);

如果使用者发送字符串false,解码将失败。因为JSON解码无法解码和分配请求。我不介意将此作为错误处理/验证的第一层。但是,我可以自定义错误消息。我不想向消费者公开API的底层细节


我在这一带找不到好的图案

即使json.Decode出现错误,根据错误的不同,解析结果的结构可能仍然包含一些结果。从Go文档中,如果您试图解析类型错误的JSON字符串
JSON.Decode
将返回类型错误。比如:

package main

import (
    "encoding/json"
    "fmt"
)

type Program struct {
    ProgramKey string `json:"program_key"`
    Active     bool   `json:"active"`
}

func (p *Program) String() string {
    return fmt.Sprintf("&Program{ProgramKey: %s, Active: %t", p.ProgramKey, p.Active)
}

func ParseProgram(jsonStr string) (*Program, error) {
    var p *Program
    err := json.Unmarshal([]byte(jsonStr), &p)
    if err != nil {
        switch err.(type) {
        case *json.UnmarshalTypeError:
            // Maybe log this or build a debug message from it.
            fmt.Println(err)
        default:
            return p, err
        }
    }
    // Inspect P further since it might still contain valid info.
    // ...
    return p, nil
}

func main() {
    jsonStr := `
        {
            "program_key": "example-key",
            "active": "false"
        }
    `
    p, err := ParseProgram(jsonStr)
    if err != nil {
        panic(err)
    }

    fmt.Println(p)
}
产生:

json: cannot unmarshal string into Go struct field Program.active of type bool
&Program{ProgramKey: example-key, Active: false
请注意,main中的
p
仍然填充了
ProgramKey
字段