package main
import (
"fmt"
"reflect"
"encoding/json"
)
type Func struct {
Method string `json:"method" descr:"Method name"`
Params struct {
Address string `json:"address" descr:"Target address"`
Count string `json:"count" descr:"Count of retrains"`
ReqNum int `json:"reqNum"`
} `json:"params"`
}
/* JSON Schema Generator */
func Reflector(value interface{}) map[string]interface{} {
var reflector func(name string, descr string, value interface{}, depth int) map[string]interface{}
reflector = func(name string, descr string, value interface{}, depth int) map[string]interface{} {
sMap := make(map[string]interface{})
rValue := reflect.ValueOf(value)
rValue = reflect.Indirect(rValue)
rType := rValue.Type()
if depth == 0 {
sMap["$schema"] = "http://json-schema.org/draft-04/schema#"
}
if len(descr) > 0 {
sMap["description"] = descr
}
switch rType.Kind() {
case reflect.String:
sMap["type"] = "string"
case reflect.Int, reflect.Int64:
sMap["type"] = "integer"
case reflect.Float32, reflect.Float64:
sMap["type"] = "number"
case reflect.Bool:
sMap["type"] = "bool"
case reflect.Struct:
sMap["type"] = "object"
req := make([]string, 0)
newMap := make(map[string]interface{})
for i := 0; i < rType.NumField(); i++ {
fieldValue := rValue.Field(i)
fieldName := rType.Field(i).Name
jsonTag, ok := rType.Field(i).Tag.Lookup("json")
if ok {
fieldName = jsonTag
}
req = append(req, fieldName)
descrTag, ok := rType.Field(i).Tag.Lookup("descr")
newMap[fieldName] = reflector(fieldName, descrTag, fieldValue.Interface(), depth + 1)
}
sMap["required"] = req
sMap["properties"] = newMap
}
return sMap
}
return reflector("", "", value, 0)
}
type Descr struct {
Type string `json:"type"`
Name string `json:"name,omitempty"`
Descr string `json:"description,omitempty"`
Value interface{} `json:"value,omitempty"`
Props []Descr `json:"fields,omitempty"`
}
func reflector2(name string, tDescr string, value interface{}, depth int) Descr {
var descr Descr
rType := reflect.TypeOf(value)
rValue := reflect.ValueOf(value)
if depth == 0 {
}
if len(tDescr) > 0 {
descr.Descr = tDescr
}
descr.Name = name
switch rType.Kind() {
case reflect.String:
descr.Type = "string"
descr.Value = rValue.String()
case reflect.Int, reflect.Int64:
descr.Type = "integer"
descr.Value = rValue.Int()
case reflect.Float32, reflect.Float64:
descr.Type = "number"
case reflect.Bool:
descr.Type = "bool"
case reflect.Struct:
descr.Type = "object"
//req := make([]string, 0)
descr.Props = make([]Descr, 0)
for i := 0; i < rType.NumField(); i++ {
fieldValue := rValue.Field(i)
fieldName := rType.Field(i).Name
jsonTag, ok := rType.Field(i).Tag.Lookup("json")
if ok {
fieldName = jsonTag
}
//req = append(req, fieldName)
descrTag, ok := rType.Field(i).Tag.Lookup("descr")
descr.Props = append(descr.Props, reflector2(fieldName, descrTag, fieldValue.Interface(), depth + 1))
}
}
return descr
}
func main() {
fu := Func{
Method: "Add",
}
res := Reflector(&fu)
//res := reflector2("","", fu, 0) //Reflector(fu)
j, _ := json.MarshalIndent(res, "", " ")
fmt.Println(string(j))
}