From e41868db0896b08e7d08963b52da1121c3658ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Mon, 10 Jan 2022 23:26:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9E=84=E5=BB=BAJSON=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=90=8C=E6=97=B6,=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E7=B1=BB=E5=9E=8B=E4=BB=A5=E5=8F=8A=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- json_tool/json_test.go | 42 +++++++++++ json_tool/parse.go | 166 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 205 insertions(+), 3 deletions(-) diff --git a/json_tool/json_test.go b/json_tool/json_test.go index 8638c9d..5e8df88 100644 --- a/json_tool/json_test.go +++ b/json_tool/json_test.go @@ -125,3 +125,45 @@ func TestParse(t *testing.T) { byteData, _ := json.Marshal(source) fmt.Println(GetJSONDataStruct(string(byteData))) } + +// TestParseWithType 测试获取JSON数据结构 +// +// Author : go_developer@163.com<张德满> +// +// Date : 10:59 PM 2022/1/9 +func TestParseWithType(t *testing.T) { + source := map[string]interface{}{ + "name": "zhangdeman", + "extra": map[string]interface{}{ + "age": 18, + "height": 180, + "slice": []int{1, 2, 3}, + "obj": map[string]interface{}{ + "la": "aaaa", + }, + }, + "slice": []int{1, 2, 3}, + "map": map[string]interface{}{"a": 1, "d": 5.5, "e": "qqq"}, + "empty_obj": map[string]interface{}{}, + "empty_list": make([]interface{}, 0), + "table": []map[string]interface{}{ + {"name": "alex", "age": 18, "number": 1, "obj": map[string]interface{}{"enen": "en"}}, + {"name": "bob", "age": 28, "number": 2}, + }, + "two_slice": []map[string]interface{}{ + { + "students": []map[string]interface{}{ + { + "name": "enen", + "age": 18, + "score": []float64{1, 2, 3, 45}, + }, + }, + "other": []interface{}{"others"}, + "read_only": 1, + }, + }, + } + byteData, _ := json.Marshal(source) + fmt.Println(GetJSONDataStructWithType(string(byteData))) +} diff --git a/json_tool/parse.go b/json_tool/parse.go index 6b77582..79f231a 100644 --- a/json_tool/parse.go +++ b/json_tool/parse.go @@ -8,10 +8,52 @@ package json_tool import ( + "strings" + "github.com/pkg/errors" "github.com/tidwall/gjson" ) +// Field ... +// +// Author : go_developer@163.com<张德满> +// +// Date : 2022/1/10 10:47 PM +type Field struct { + Path string `json:"path"` // 路径 + Type string `json:"type"` // 类型 + Example string `json:"example"` // 示例值 +} + +const ( + // FieldTypeInt ... + FieldTypeInt = "int64" + // FieldTypeIntSlice ... + FieldTypeIntSlice = "[]int64" + // FieldTypeFloat ... + FieldTypeFloat = "float64" + // FieldTypeFloatSlice ... + FieldTypeFloatSlice = "[]float64" + // FieldTypeBool ... + FieldTypeBool = "bool" + // FieldTypeBoolSlice ... + FieldTypeBoolSlice = "[]bool" + // FieldTypeString ... + FieldTypeString = "string" + // FieldTypeStringSLice ... + FieldTypeStringSLice = "string" + // FieldTypeAny ... + FieldTypeAny = "interface{}" + // FieldTypeAnySlice ... + FieldTypeAnySlice = "[]interface{}" + // FieldTypeSlice ... + FieldTypeSlice = "[]interface{}" + // FieldTypeMap ... + FieldTypeMap = "map" + // FieldTypeMapSlice ... + FieldTypeMapSlice = "[]map" +) + // GetJSONDataStruct 获取JSON数据的结构 // // Author : go_developer@163.com<张德满> @@ -24,10 +66,18 @@ func GetJSONDataStruct(data string) ([]string, error) { pathList := make([]string, 0) r := gjson.Parse(data) r.ForEach(func(key, value gjson.Result) bool { + if value.Value() == nil { + pathList = append(pathList, key.String()) + return true + } if value.IsObject() { - list, _ := GetJSONDataStruct(value.String()) - for _, k := range list { - pathList = append(pathList, key.String()+"."+k) + if value.String() == "{}" { + pathList = append(pathList, key.String()) + } else { + list, _ := GetJSONDataStruct(value.String()) + for _, k := range list { + pathList = append(pathList, key.String()+"."+k) + } } } @@ -55,3 +105,113 @@ func GetJSONDataStruct(data string) ([]string, error) { }) return pathList, nil } + +// GetJSONDataStructWithType 获取数据结构,并获取类型 +// +// Author : go_developer@163.com<张德满> +// +// Date : 2022/1/10 10:47 PM +func GetJSONDataStructWithType(data string) ([]Field, error) { + if !gjson.Valid(data) { + return make([]Field, 0), errors.New("JSON format is invalid") + } + pathList := make([]Field, 0) + r := gjson.Parse(data) + r.ForEach(func(key, value gjson.Result) bool { + if value.Value() == nil { + pathList = append(pathList, Field{ + Path: key.String(), + Type: FieldTypeAny, + Example: "nil", + }) + return true + } + if value.IsObject() { + if value.String() == "{}" { + pathList = append(pathList, Field{ + Path: key.String(), + Type: FieldTypeMap, + Example: "{}", + }) + } else { + list, _ := GetJSONDataStructWithType(value.String()) + for _, field := range list { + pathList = append(pathList, Field{ + Path: key.String() + "." + field.Path, + Type: field.Type, + Example: field.Example, + }) + } + } + } + + if value.IsArray() { + dataList := value.Array() + if len(dataList) > 0 { + if !dataList[0].IsObject() && !dataList[0].IsArray() { + pathList = append(pathList, Field{ + Path: key.String(), + Type: "[]" + GetDataType(dataList[0]), + Example: value.String(), + }) + } else { + list, _ := GetJSONDataStructWithType(dataList[0].String()) + for _, field := range list { + pathList = append(pathList, Field{ + Path: key.String() + ".[]." + field.Path, + Type: field.Type, + Example: field.Example, + }) + } + } + } else { + pathList = append(pathList, Field{ + Path: key.String(), + Type: FieldTypeSlice, + Example: "[]", + }) + } + } + + if !value.IsObject() && !value.IsArray() { + pathList = append(pathList, Field{ + Path: key.String(), + Type: GetDataType(value), + Example: value.String(), + }) + } + + return true + }) + return pathList, nil +} + +// GetDataType 获取数据类型 +// +// Author : go_developer@163.com<张德满> +// +// Date : 2022/1/10 11:00 PM +func GetDataType(value gjson.Result) string { + switch value.Type.String() { + default: + return FieldTypeAny + case "Null": + return FieldTypeAny + case "False": + return FieldTypeBool + case "True": + return FieldTypeBool + case "Number": + if strings.Contains(value.String(), ".") { + return FieldTypeFloat + } + return FieldTypeInt + case "String": + return FieldTypeString + case "JSON": + if strings.HasPrefix(strings.TrimSpace(value.String()), "[") { + return FieldTypeSlice + } + return FieldTypeMap + } +}