最近工作遇到一个问题,需要解析一个前端传递过来的json,json 串大概是这样
{
"type":"array",
"items":{
"type":"number"
},
"properties":{
"name":{
"type":"string"
},
"id":{
"type":"number"
}
}
}
外层是一个schema,属性对应items 也是一个schema,properties 对应的是一个字典,每个元素是一个schema 。
首先想到的第一个schema,items 和 properties 分别引用这个schema
type schema struct {
Type string
Items schema
Properties map[string]schema
}
出现语法错误 Invalid recursive type 'schema' ,错误的递归类型schema。
golang 不支持strut递归创建。
不递归创建,在创建中属性保存一个指向schema对象的指针。
type schema struct {
Type string `json:"type"`
Items *schema `json:"items"`
Properties map[string]*schema `json:"properties"`
}
语法上没啥问题。
func main(){
var res schema
str := "{\"type\":\"array\",\"items\":{\"properties\":{\"id\":{\"type\":\"number\"},\"name\":{\"type\":\"string\"}},\"type\":\"object\"}}"
if err := json.Unmarshal([]byte(str), &res); err != nil {
panic(err)
}
fmt.Println(res.Items.Properties["id"].Type)
}
type schema struct {
Type string `json:"type"`
Items *schema `json:"items"`
Properties map[string]*schema `json:"properties"`
}
打印结果为 number 。
下面看个例子,重载Schema
package main
import (
"encoding/json"
"fmt"
)
type SchemaRef struct {
Ref string
Value *Schema
}
type Schemas map[string]*SchemaRef
type Schema struct {
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Items *SchemaRef `json:"items,omitempty" yaml:"items,omitempty"`
Properties Schemas `json:"properties,omitempty" yaml:"properties,omitempty"`
}
func (schemaRef *SchemaRef) MarshalJSON() (res []byte, err error) {
schema := *schemaRef.Value
res, err = json.Marshal(schema)
if err != nil {
return
}
return
}
func (schemaRef *SchemaRef) UnmarshalJSON(data []byte) error {
var schema Schema
err := json.Unmarshal(data, &schema)
if err != nil {
return err
}
schemaRef.Ref = ""
schemaRef.Value = &schema
return nil
}
func main() {
var res Schema
str := "{"type":"array","items":{"properties":{"id":{"type":"number"},"name":{"type":"string"}},"type":"object"}}"
if err := json.Unmarshal([]byte(str), &res); err != nil {
panic(err)
}
fmt.Println(res.Items.Value.Properties["id"].Value.Type)
jsonStr, _ := json.Marshal(&res)
fmt.Println(string(jsonStr))
}
- Items 属性指向schemaRef,Schemas 为 map[string]*SchemaRef ,通过重载来接受json转换。
- 定义了 UnmarshalJSON 方法,此方法解析json之后,然后对schemaRef 本身赋值,改变了json原本的结构。
- 定义了 MarshalJSON 此方法,把 schemaRef.Value 拿出来序列化成字符串,然后返回。
- 本质上还是沿用json 包的基本方法,然后对此做了调整。