fix:json to struct

feat:anyutil error code
This commit is contained in:
李斌
2023-03-24 11:18:48 +08:00
parent 36cb205333
commit 1917b21823
11 changed files with 291 additions and 134 deletions

View File

@@ -2,29 +2,13 @@ package jsonUtil
import (
"encoding/json"
"errors"
"fmt"
"github.com/jefferyjob/go-easy-utils"
"reflect"
"strconv"
"strings"
)
// JsonToStruct 将 JSON 字符串解析为指定的结构体指针
// 根据结构体的字段类型和标签来自动选择将 JSON 值转换为相应的类型。
//
// 支持的字段类型包括 string、int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、bool、float32 和 float64。
//
// 支持的标签有 "json"、"jsonb" 和 "mapstructure"。
// - "json" 和 "jsonb" 标签指示解析 JSON 时使用的键名。
// - "mapstructure" 标签指示字段名的映射关系。
//
// 如果 JSON 中的某些键在结构体中没有对应的字段,则它们将被忽略。
// 如果 JSON 中的某些键的类型与结构体中的字段类型不匹配,则会引发解析错误。
//
// 参数 jsonData 是要解析的 JSON 字符串。
// 参数 result 是指向要填充 JSON 值的结构体指针。
//
// 如果解析成功,则返回 nil。如果解析失败则返回解析错误。
func JsonToStruct(jsonData string, result interface{}) error {
var data map[string]interface{}
err := json.Unmarshal([]byte(jsonData), &data)
@@ -57,7 +41,7 @@ func JsonToStruct(jsonData string, result interface{}) error {
switch fieldValue.Kind() {
case reflect.String:
fieldValue.SetString(value.(string))
fieldValue.SetString(toString(value))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
val, err := toInt64(value)
if err != nil {
@@ -76,10 +60,16 @@ func JsonToStruct(jsonData string, result interface{}) error {
return err
}
fieldValue.SetFloat(val)
case reflect.Bool:
val := toBool(value)
fieldValue.SetBool(val)
case reflect.Struct:
if subData, ok := value.(map[string]interface{}); ok {
subResult := reflect.New(fieldValue.Type())
JsonToStruct(convertToJSONString(subData), subResult.Interface())
err := JsonToStruct(convertToJSONString(subData), subResult.Interface())
if err != nil {
return err
}
fieldValue.Set(subResult.Elem())
}
case reflect.Slice:
@@ -92,7 +82,10 @@ func JsonToStruct(jsonData string, result interface{}) error {
if subElem.Kind() == reflect.Struct {
if subDataElem, ok := subValue.(map[string]interface{}); ok {
subResultElem := reflect.New(subElem.Type())
JsonToStruct(convertToJSONString(subDataElem), subResultElem.Interface())
err := JsonToStruct(convertToJSONString(subDataElem), subResultElem.Interface())
if err != nil {
return err
}
subElem.Set(subResultElem.Elem())
}
} else {
@@ -101,8 +94,8 @@ func JsonToStruct(jsonData string, result interface{}) error {
}
fieldValue.Set(subResult)
}
default:
fieldValue.Set(reflect.ValueOf(value))
//default:
// fieldValue.Set(reflect.ValueOf(value))
}
}
@@ -114,7 +107,71 @@ func convertToJSONString(data map[string]interface{}) string {
return string(jsonBytes)
}
func toBool(value interface{}) bool {
switch v := value.(type) {
case bool:
return v
case string:
return v != "" && v != "false" && v != "0"
case int, int8, int16, int32, int64:
return v != 0
case uint, uint8, uint16, uint32, uint64, uintptr:
return v != 0
case float32, float64:
return v != 0.0
case complex64, complex128:
return v != 0+0i
case nil:
return false
default:
return false
}
}
func toString(value interface{}) string {
if value == nil {
return ""
}
switch v := value.(type) {
case string:
return v
case int:
return strconv.Itoa(v)
case int8:
return strconv.FormatInt(int64(v), 10)
case int16:
return strconv.FormatInt(int64(v), 10)
case int32:
return strconv.FormatInt(int64(v), 10)
case int64:
return strconv.FormatInt(v, 10)
case uint:
return strconv.FormatUint(uint64(v), 10)
case uint8:
return strconv.FormatUint(uint64(v), 10)
case uint16:
return strconv.FormatUint(uint64(v), 10)
case uint32:
return strconv.FormatUint(uint64(v), 10)
case uint64:
return strconv.FormatUint(v, 10)
case float32:
return strconv.FormatFloat(float64(v), 'f', -1, 32)
case float64:
return strconv.FormatFloat(v, 'f', -1, 64)
case bool:
return strconv.FormatBool(v)
default:
return ""
}
}
func toInt64(value interface{}) (int64, error) {
if value == nil {
return 0, nil
}
switch value.(type) {
case float32:
return int64(value.(float32)), nil
@@ -123,7 +180,7 @@ func toInt64(value interface{}) (int64, error) {
case string:
intValue, err := strconv.ParseInt(value.(string), 10, 64)
if err != nil {
return 0, err
return 0, go_easy_utils.ErrSyntax
}
return intValue, nil
case int:
@@ -136,21 +193,35 @@ func toInt64(value interface{}) (int64, error) {
return int64(value.(int32)), nil
case int64:
return value.(int64), nil
case interface{}:
return 0, nil
default:
return 0, errors.New(fmt.Sprintf("jsonUtils toInt64 err: %T \n", value))
return 0, go_easy_utils.ErrType
}
}
func toUint64(value interface{}) (uint64, error) {
if value == nil {
return 0, nil
}
switch value.(type) {
case float32:
return uint64(value.(float32)), nil
v := value.(float32)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case float64:
return uint64(value.(float64)), nil
v := value.(float64)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case string:
intValue, err := strconv.ParseUint(value.(string), 10, 64)
if err != nil {
return 0, err
return 0, go_easy_utils.ErrSyntax
}
return intValue, nil
case uint:
@@ -163,22 +234,60 @@ func toUint64(value interface{}) (uint64, error) {
return uint64(value.(uint32)), nil
case uint64:
return value.(uint64), nil
case int:
v := value.(int)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case int8:
v := value.(int8)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case int16:
v := value.(int16)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case int32:
v := value.(int32)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case int64:
v := value.(int64)
if v < 0 {
return 0, nil
}
return uint64(v), nil
case interface{}:
return 0, nil
default:
return 0, errors.New(fmt.Sprintf("jsonUtils toUint64 err: %T \n", value))
return 0, go_easy_utils.ErrType
}
}
func toFloat64(value interface{}) (float64, error) {
if value == nil {
return 0, nil
}
switch value.(type) {
case float32:
return float64(value.(float32)), nil
case float64:
return value.(float64), nil
case string:
floatValue, err := strconv.ParseFloat(value.(string), 64)
if err != nil {
return 0, err
return 0, go_easy_utils.ErrSyntax
}
return floatValue, nil
default:
return 0, errors.New(fmt.Sprintf("jsonUtils toFloat64 err: %T \n", value))
return 0, go_easy_utils.ErrType
}
}