mirror of
https://github.com/eolinker/apinto
synced 2025-09-27 13:12:20 +08:00
348 lines
8.4 KiB
Go
348 lines
8.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/brianvoe/gofakeit/v6"
|
|
"math/rand"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/robertkrimen/otto"
|
|
)
|
|
|
|
// JSObjectToJSON 将js对象转为json
|
|
func JSObjectToJSON(s string) ([]byte, error) {
|
|
vm := otto.New()
|
|
v, err := vm.Run(fmt.Sprintf(`
|
|
cs = %s
|
|
JSON.stringify(cs)
|
|
`, s))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(v.String()), nil
|
|
}
|
|
|
|
// JSONUnmarshal 将json格式的s解码成v所需的json格式
|
|
func JSONUnmarshal(s, v interface{}) error {
|
|
data, err := json.Marshal(s)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return json.Unmarshal(data, v)
|
|
}
|
|
|
|
// JsonSchemaMockJsUnmarshal
|
|
// 解析mockJs生成的json schema 并根据规则生成随机值
|
|
// 不是mockJs生成的json 走默认规则解析
|
|
func JsonSchemaMockJsUnmarshal(valueMap interface{}) interface{} {
|
|
rand.Seed(time.Now().UnixMicro())
|
|
gofakeit.Seed(time.Now().UnixMicro())
|
|
|
|
value, vOk := valueMap.(map[string]interface{})
|
|
if vOk {
|
|
switch valType := value["properties"].(type) {
|
|
case []interface{}:
|
|
resultMap := make(map[string]interface{})
|
|
for _, v := range valType {
|
|
if m, ok := v.(map[string]interface{}); ok {
|
|
name, nameOk := m["name"].(string)
|
|
if !nameOk {
|
|
return jsonSchemaFormat
|
|
}
|
|
template := m["template"]
|
|
if t, tOk := m["type"].(string); tOk {
|
|
rule, ruleOk := m["rule"].(map[string]interface{})
|
|
if !ruleOk || len(rule) == 0 {
|
|
if template != nil {
|
|
resultMap[name] = mockConstant(template)
|
|
continue
|
|
}
|
|
}
|
|
|
|
switch t {
|
|
case "string":
|
|
|
|
minVal, maxVal, _, _, err := getMinMaxDminDmax(rule)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
randomNum := 0
|
|
if minVal > 0 && maxVal == 0 {
|
|
randomNum = int(minVal)
|
|
}
|
|
|
|
if minVal > 0 && maxVal > 0 {
|
|
randomNum = int(RandInt64(int64(minVal), int64(maxVal)))
|
|
}
|
|
|
|
if template != nil {
|
|
templateStr, sOk := template.(string)
|
|
if !sOk {
|
|
return jsonSchemaFormat
|
|
}
|
|
temp := ""
|
|
for i := 0; i < randomNum; i++ {
|
|
temp = temp + templateStr
|
|
}
|
|
resultMap[name] = temp
|
|
continue
|
|
}
|
|
|
|
case "number":
|
|
minVal, maxVal, dminVal, dmaxVal, err := getMinMaxDminDmax(rule)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
randomValue := 0.0
|
|
if minVal > 0.0 && maxVal == 0.0 {
|
|
randomValue = minVal
|
|
randomValue += RandFloats(0, 1)
|
|
} else if minVal > 0.0 && maxVal > 0.0 {
|
|
randomValue = RandFloats(minVal, maxVal)
|
|
}
|
|
|
|
if randomValue == 0.0 {
|
|
resultMap[name] = template
|
|
continue
|
|
}
|
|
|
|
if dminVal > 0.0 && dmaxVal == 0.0 {
|
|
randomValue, _ = strconv.ParseFloat(strconv.FormatFloat(randomValue, 'f', int(dminVal), 64), 64)
|
|
} else if dminVal > 0.0 && dmaxVal > 0.0 {
|
|
floats := RandFloats(dminVal, dmaxVal)
|
|
randomValue, _ = strconv.ParseFloat(strconv.FormatFloat(randomValue, 'f', int(floats), 64), 64)
|
|
} else {
|
|
randomValue, _ = strconv.ParseFloat(strconv.FormatFloat(randomValue, 'f', 0, 64), 64)
|
|
}
|
|
|
|
resultMap[name] = randomValue
|
|
|
|
case "boolean":
|
|
resultMap[name] = gofakeit.Bool()
|
|
case "object":
|
|
templateMap, templateOk := template.(map[string]interface{})
|
|
if templateOk {
|
|
minVal, maxVal, _, _, err := getMinMaxDminDmax(rule)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
randomNum := 0
|
|
if minVal > 0 && maxVal == 0 {
|
|
randomNum = int(minVal)
|
|
}
|
|
|
|
if minVal > 0 && maxVal > 0 {
|
|
randomNum = int(RandInt64(int64(minVal), int64(maxVal)))
|
|
}
|
|
tempMap := make(map[string]interface{})
|
|
i := 1
|
|
for key, val := range templateMap {
|
|
|
|
split := strings.Split(key, "|")
|
|
tempMap[split[0]] = mockConstant(val)
|
|
|
|
if i == randomNum {
|
|
break
|
|
}
|
|
i++
|
|
}
|
|
|
|
resultMap[name] = tempMap
|
|
|
|
}
|
|
case "array":
|
|
templateList, templateOk := template.([]interface{})
|
|
if templateOk {
|
|
minVal, maxVal, _, _, err := getMinMaxDminDmax(rule)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
randomNum := 0
|
|
if minVal > 0.0 && maxVal == 0.0 {
|
|
randomNum = int(minVal)
|
|
}
|
|
|
|
if minVal > 0.0 && maxVal > 0.0 {
|
|
randomNum = int(RandInt64(int64(minVal), int64(maxVal)))
|
|
}
|
|
|
|
if randomNum == 1 {
|
|
if len(templateList) > 1 {
|
|
resultMap[name] = templateList[rand.Intn(len(templateList))]
|
|
continue
|
|
}
|
|
switch templateVal := templateList[0].(type) {
|
|
case map[string]interface{}:
|
|
tempMap := make(map[string]interface{})
|
|
for key, val := range templateVal {
|
|
split := strings.Split(key, "|")
|
|
tempMap[split[0]] = mockConstant(val)
|
|
}
|
|
resultMap[name] = tempMap
|
|
default:
|
|
resultMap[name] = templateVal
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
tempList := make([]interface{}, 0)
|
|
|
|
for i := 0; i < randomNum; i++ {
|
|
|
|
for _, templateType := range templateList {
|
|
switch templateVal := templateType.(type) {
|
|
case map[string]interface{}:
|
|
tempMap := make(map[string]interface{})
|
|
for key, val := range templateVal {
|
|
split := strings.Split(key, "|")
|
|
tempMap[split[0]] = mockConstant(val)
|
|
}
|
|
tempList = append(tempList, tempMap)
|
|
default:
|
|
tempList = append(tempList, templateType)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
resultMap[name] = tempList
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return resultMap
|
|
}
|
|
}
|
|
return jsonSchemaUnmarshal(value)
|
|
}
|
|
|
|
func mockConstant(v interface{}) interface{} {
|
|
if templateStr, ok := v.(string); ok {
|
|
templateStr = strings.ToLower(templateStr)
|
|
switch templateStr {
|
|
case "@cname":
|
|
return gofakeit.Username()
|
|
case "@cfirst":
|
|
return gofakeit.FirstName()
|
|
case "@clast":
|
|
return gofakeit.LastName()
|
|
case "@name", "@name(true)":
|
|
return gofakeit.Name()
|
|
case "@first":
|
|
return gofakeit.FirstName()
|
|
case "@last":
|
|
return gofakeit.LastName()
|
|
case "@email":
|
|
return gofakeit.Email()
|
|
case "@ip":
|
|
return gofakeit.IPv4Address()
|
|
case "@zip":
|
|
return gofakeit.Address().Zip
|
|
case "@city", "@city(true)":
|
|
return gofakeit.Address().Address
|
|
case "@url":
|
|
return gofakeit.URL()
|
|
default:
|
|
return v
|
|
}
|
|
}
|
|
return v
|
|
}
|
|
|
|
var jsonSchemaFormat = errors.New("json schema format err")
|
|
|
|
func getMinMaxDminDmax(rule map[string]interface{}) (float64, float64, float64, float64, error) {
|
|
minVal := 0.0
|
|
min, minOk := rule["min"]
|
|
if minOk && min != nil {
|
|
mOk := false
|
|
minVal, mOk = min.(float64)
|
|
if !mOk {
|
|
return 0, 0, 0, 0, jsonSchemaFormat
|
|
}
|
|
|
|
}
|
|
|
|
maxVal := 0.0
|
|
max, maxOk := rule["max"]
|
|
if maxOk && max != nil {
|
|
mOk := false
|
|
maxVal, mOk = max.(float64)
|
|
if !mOk {
|
|
return 0, 0, 0, 0, jsonSchemaFormat
|
|
}
|
|
}
|
|
dminVal := 0.0
|
|
dmin, dminOk := rule["dmin"]
|
|
if dminOk && dmin != nil {
|
|
mOk := false
|
|
dminVal, mOk = dmin.(float64)
|
|
if !mOk {
|
|
return 0, 0, 0, 0, jsonSchemaFormat
|
|
}
|
|
}
|
|
|
|
dmaxVal := 0.0
|
|
dmax, dmaxOk := rule["dmax"]
|
|
if dmaxOk && dmax != nil {
|
|
mOk := false
|
|
dmaxVal, mOk = dmax.(float64)
|
|
if !mOk {
|
|
return 0, 0, 0, 0, jsonSchemaFormat
|
|
}
|
|
}
|
|
return minVal, maxVal, dminVal, dmaxVal, nil
|
|
}
|
|
|
|
func jsonSchemaUnmarshal(properties interface{}) interface{} {
|
|
propertiesMap, ok := properties.(map[string]interface{})
|
|
if !ok {
|
|
return jsonSchemaFormat
|
|
}
|
|
if val, ok := propertiesMap["example"]; ok {
|
|
return val
|
|
} else {
|
|
if t, tOk := propertiesMap["type"].(string); tOk {
|
|
switch t {
|
|
case "string":
|
|
return gofakeit.LetterN(10)
|
|
case "number":
|
|
return gofakeit.Float64()
|
|
case "integer":
|
|
return gofakeit.Int64()
|
|
case "boolean":
|
|
return gofakeit.Bool()
|
|
case "object":
|
|
propertiesMaps, pOk := propertiesMap["properties"].(map[string]interface{})
|
|
if !pOk {
|
|
return jsonSchemaFormat
|
|
}
|
|
resultMap := make(map[string]interface{})
|
|
for key, vProperties := range propertiesMaps {
|
|
resultMap[key] = jsonSchemaUnmarshal(vProperties)
|
|
}
|
|
return resultMap
|
|
case "array":
|
|
items, iOk := propertiesMap["items"].(map[string]interface{})
|
|
if !iOk {
|
|
return jsonSchemaFormat
|
|
}
|
|
resultList := make([]interface{}, 0)
|
|
resultList = append(resultList, jsonSchemaUnmarshal(items))
|
|
return resultList
|
|
}
|
|
}
|
|
return jsonSchemaFormat
|
|
}
|
|
}
|