Golang中结构体对象列表的JSON Schema实现

Golang中结构体对象列表的JSON Schema实现 今天开始接触Go语言…总的来说我很喜欢它,但还有一些概念我正在努力理解,比如如何创建一个包含元组的结构体…我有以下想要响应的JSON模式。

[
 {
  "cmd": "string",
  "service": "string",
  "src": "string",
  "dest": "string",
  "weight": float,
  "tags": ["string"],
  "opts": {"string":"string"}
 }
]

并且我有以下代码

type consulService struct {
    Cmd     string   `json:"cmd"`
    Service string   `json:"service"`
    Src     string   `json:"src"`
    Dest    string   `json:"dest"`
    Weight  float32  `json:"weight"`
    Tags    []string `json:"tags"`
    Opts    []string `json:"opts"`
}

func getConsulServices(w http.ResponseWriter, req *http.Request) {

    consultServiceCatalg := []consulService{
        {
            Cmd:     "test",
            Service: "CustomService",
            Src:     "/",
            Dest:    "http://1.1.1.1:5555/",
            Weight:  100,
            Tags:    []string{"custom","service"},
            Opts:    {"k1" :"s1", "k2": "s2", "Kn":"etc"},
        },
    }

    fmt.Println(consultServiceCatalg)

    js, err := json.Marshal(consultServiceCatalg)

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")

    w.Write(js)
}

我的问题是Opts变量…我如何在类型对象中表示一个字符串列表…我是否需要创建一个新的类型Opts…其键值对类型为字符串…简而言之就是一个元组,但我没能在Golang中找到这种类型…

这里最大的问题是键是动态的而不是静态的。

这对于有超过一天Go语言经验的人来说可能显而易见。谢谢。


更多关于Golang中结构体对象列表的JSON Schema实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

map[string]string

更多关于Golang中结构体对象列表的JSON Schema实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢为我指明了正确的方向。

我学习了关于映射的知识。

type consulService struct {
    Cmd     string            `json:"cmd"`
    Service string            `json:"service"`
    Src     string            `json:"src"`
    Dst     string            `json:"dst"`
    Weight  float32           `json:"weight"`
    Tags    []string          `json:"tags"`
    Opts    map[string]string `json:"opts"`
}

func getConsulServices(w http.ResponseWriter, req *http.Request) {

    consultServiceCatalg := []consulService{
        {
            Cmd:     "route add",
            Service: "CustomService",
            Src:     "/home",
            Dst:     "http://1.1.1.1",
            Weight:  100,
            Tags:    []string{"custom"},
            Opts:    map[string]string{"strip": "/path", "proto": "tcp"},
        },
    }

在Go语言中,处理动态键值对(键是字符串,值也是字符串)的正确方式是使用map[string]string类型。你的Opts字段应该定义为这种类型,而不是[]string

以下是修正后的代码:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type consulService struct {
    Cmd     string            `json:"cmd"`
    Service string            `json:"service"`
    Src     string            `json:"src"`
    Dest    string            `json:"dest"`
    Weight  float32           `json:"weight"`
    Tags    []string          `json:"tags"`
    Opts    map[string]string `json:"opts"`  // 使用map而不是slice
}

func getConsulServices(w http.ResponseWriter, req *http.Request) {
    consulServiceCatalog := []consulService{
        {
            Cmd:     "test",
            Service: "CustomService",
            Src:     "/",
            Dest:    "http://1.1.1.1:5555/",
            Weight:  100,
            Tags:    []string{"custom", "service"},
            Opts: map[string]string{  // 正确初始化map
                "k1": "s1",
                "k2": "s2",
                "Kn": "etc",
            },
        },
    }

    fmt.Printf("结构体数据: %+v\n", consulServiceCatalog)

    js, err := json.MarshalIndent(consulServiceCatalog, "", "  ")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}

func main() {
    // 测试JSON序列化
    testData := []consulService{
        {
            Cmd:     "test",
            Service: "CustomService",
            Src:     "/",
            Dest:    "http://1.1.1.1:5555/",
            Weight:  100,
            Tags:    []string{"custom", "service"},
            Opts: map[string]string{
                "k1": "s1",
                "k2": "s2",
                "Kn": "etc",
            },
        },
    }

    jsonData, _ := json.MarshalIndent(testData, "", "  ")
    fmt.Println("生成的JSON:")
    fmt.Println(string(jsonData))
}

输出结果:

[
  {
    "cmd": "test",
    "service": "CustomService",
    "src": "/",
    "dest": "http://1.1.1.1:5555/",
    "weight": 100,
    "tags": [
      "custom",
      "service"
    ],
    "opts": {
      "k1": "s1",
      "k2": "s2",
      "Kn": "etc"
    }
  }
]

如果需要处理更复杂的值类型(不仅仅是字符串),可以使用map[string]interface{}

type consulService struct {
    Cmd     string                 `json:"cmd"`
    Service string                 `json:"service"`
    Src     string                 `json:"src"`
    Dest    string                 `json:"dest"`
    Weight  float32                `json:"weight"`
    Tags    []string               `json:"tags"`
    Opts    map[string]interface{} `json:"opts"`  // 支持多种类型的值
}

// 使用示例
service := consulService{
    Cmd:     "test",
    Service: "CustomService",
    Src:     "/",
    Dest:    "http://1.1.1.1:5555/",
    Weight:  100,
    Tags:    []string{"custom", "service"},
    Opts: map[string]interface{}{
        "timeout": 30,      // int
        "enabled": true,    // bool
        "name":    "test",  // string
        "tags":    []string{"a", "b", "c"},  // slice
    },
}

对于JSON Schema验证,可以使用第三方库如github.com/xeipuuv/gojsonschema

import "github.com/xeipuuv/gojsonschema"

func validateJSONSchema(data []byte) error {
    schemaLoader := gojsonschema.NewStringLoader(`{
        "type": "array",
        "items": {
            "type": "object",
            "properties": {
                "cmd": {"type": "string"},
                "service": {"type": "string"},
                "src": {"type": "string"},
                "dest": {"type": "string"},
                "weight": {"type": "number"},
                "tags": {"type": "array", "items": {"type": "string"}},
                "opts": {"type": "object", "additionalProperties": {"type": "string"}}
            },
            "required": ["cmd", "service", "src", "dest", "weight", "tags", "opts"]
        }
    }`)

    documentLoader := gojsonschema.NewBytesLoader(data)
    result, err := gojsonschema.Validate(schemaLoader, documentLoader)
    
    if err != nil {
        return err
    }
    
    if !result.Valid() {
        return fmt.Errorf("JSON验证失败: %v", result.Errors())
    }
    
    return nil
}
回到顶部