mirror of
https://github.com/jefferyjob/go-easy-utils.git
synced 2025-10-16 20:11:25 +08:00
fix:json to struct
feat:anyutil error code
This commit is contained in:
25
.github/workflows/go-testing.yml
vendored
25
.github/workflows/go-testing.yml
vendored
@@ -1,25 +0,0 @@
|
|||||||
name: Go
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [testing]
|
|
||||||
pull_request:
|
|
||||||
branches: [testing]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: 1.18
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: go build -v ./...
|
|
||||||
|
|
||||||
# 运行go的单元测试
|
|
||||||
- name: Test
|
|
||||||
run: make test
|
|
4
.github/workflows/go.yml
vendored
4
.github/workflows/go.yml
vendored
@@ -2,9 +2,9 @@ name: Go
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master,main]
|
branches: [master,main,testing]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master,main]
|
branches: [master,main,testing]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package anyUtil
|
package anyUtil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"github.com/jefferyjob/go-easy-utils"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -12,15 +12,18 @@ func AnyToFloat32(value interface{}) (float32, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
fmt.Println(-math.MaxFloat32, f64, math.MaxFloat32)
|
|
||||||
if f64 < -math.MaxFloat32 || f64 > math.MaxFloat32 {
|
if f64 < -math.MaxFloat32 || f64 > math.MaxFloat32 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return float32(f64), nil
|
return float32(f64), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyToFloat64 将给定的值转换为float64
|
// AnyToFloat64 将给定的值转换为float64
|
||||||
func AnyToFloat64(v interface{}) (float64, error) {
|
func AnyToFloat64(v interface{}) (float64, error) {
|
||||||
|
if v == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
return float64(val), nil
|
return float64(val), nil
|
||||||
@@ -49,32 +52,11 @@ func AnyToFloat64(v interface{}) (float64, error) {
|
|||||||
case string:
|
case string:
|
||||||
v, err := strconv.ParseFloat(val, 64)
|
v, err := strconv.ParseFloat(val, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, ErrSyntax
|
return 0, go_easy_utils.ErrSyntax
|
||||||
}
|
}
|
||||||
return v, nil
|
return v, nil
|
||||||
|
case interface{}:
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
return 0, ErrType
|
return 0, go_easy_utils.ErrType
|
||||||
|
|
||||||
//switch reflect.TypeOf(v).Kind() {
|
|
||||||
//case reflect.Float64:
|
|
||||||
// return v.(float64), nil
|
|
||||||
//case reflect.Float32:
|
|
||||||
// return float64(v.(float32)), nil
|
|
||||||
//case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
// intVal := reflect.ValueOf(v).Int()
|
|
||||||
// if float64(intVal) > math.MaxFloat64 || float64(intVal) < -math.MaxFloat64 {
|
|
||||||
// return 0, ErrValOut
|
|
||||||
// }
|
|
||||||
// return float64(intVal), nil
|
|
||||||
//case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
// uintVal := reflect.ValueOf(v).Uint()
|
|
||||||
// if uintVal > uint64(math.MaxUint) {
|
|
||||||
// return 0, ErrValOut
|
|
||||||
// }
|
|
||||||
// return float64(uintVal), nil
|
|
||||||
//case reflect.String:
|
|
||||||
// return strconv.ParseFloat(v.(string), 64)
|
|
||||||
//default:
|
|
||||||
// return 0, ErrType
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package anyUtil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/jefferyjob/go-easy-utils"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -17,7 +18,7 @@ func AnyToInt(input interface{}) (int, error) {
|
|||||||
// int 兼容32位和64位系统
|
// int 兼容32位和64位系统
|
||||||
if int64(int(v)) != v {
|
if int64(int(v)) != v {
|
||||||
fmt.Println(int64(int(v)), v)
|
fmt.Println(int64(int(v)), v)
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
|
|
||||||
return int(v), nil
|
return int(v), nil
|
||||||
@@ -30,7 +31,7 @@ func AnyToInt8(input interface{}) (int8, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if value < math.MinInt8 || value > math.MaxInt8 {
|
if value < math.MinInt8 || value > math.MaxInt8 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return int8(value), nil
|
return int8(value), nil
|
||||||
}
|
}
|
||||||
@@ -42,7 +43,7 @@ func AnyToInt16(input interface{}) (int16, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if value < math.MinInt16 || value > math.MaxInt16 {
|
if value < math.MinInt16 || value > math.MaxInt16 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return int16(value), nil
|
return int16(value), nil
|
||||||
}
|
}
|
||||||
@@ -54,34 +55,39 @@ func AnyToInt32(input interface{}) (int32, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if value < math.MinInt32 || value > math.MaxInt32 {
|
if value < math.MinInt32 || value > math.MaxInt32 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return int32(value), nil
|
return int32(value), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyToInt64 将给定的值转换为 int64
|
// AnyToInt64 将给定的值转换为 int64
|
||||||
func AnyToInt64(value interface{}) (int64, error) {
|
func AnyToInt64(value interface{}) (int64, error) {
|
||||||
|
if value == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
switch reflect.TypeOf(value).Kind() {
|
switch reflect.TypeOf(value).Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
return reflect.ValueOf(value).Int(), nil
|
return reflect.ValueOf(value).Int(), nil
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
v := reflect.ValueOf(value).Uint()
|
v := reflect.ValueOf(value).Uint()
|
||||||
if v > math.MaxUint64 {
|
if v > math.MaxUint64 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return int64(v), nil
|
return int64(v), nil
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
v := reflect.ValueOf(value).Float()
|
v := reflect.ValueOf(value).Float()
|
||||||
if v < float64(math.MinInt64) || v > float64(math.MaxInt64) {
|
if v < float64(math.MinInt64) || v > float64(math.MaxInt64) {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return int64(v), nil
|
return int64(v), nil
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
val, err := strconv.ParseInt(value.(string), 10, 64)
|
val, err := strconv.ParseInt(value.(string), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, ErrSyntax
|
return 0, go_easy_utils.ErrSyntax
|
||||||
}
|
}
|
||||||
return val, nil
|
return val, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
return AnyToInt64(reflect.ValueOf(value).Elem().Interface())
|
||||||
}
|
}
|
||||||
return 0, ErrType
|
return 0, go_easy_utils.ErrType
|
||||||
}
|
}
|
||||||
|
@@ -2,15 +2,10 @@ package anyUtil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"github.com/jefferyjob/go-easy-utils"
|
||||||
"strconv"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestA(t *testing.T) {
|
|
||||||
fmt.Println(AnyToInt("9223372036854775806"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAnyToInt(t *testing.T) {
|
func TestAnyToInt(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
input interface{}
|
input interface{}
|
||||||
@@ -32,7 +27,7 @@ func TestAnyToInt(t *testing.T) {
|
|||||||
{input: float32(123.45), expected: 123, err: nil},
|
{input: float32(123.45), expected: 123, err: nil},
|
||||||
{input: float64(123.45), expected: 123, err: nil},
|
{input: float64(123.45), expected: 123, err: nil},
|
||||||
{input: "123", expected: 123, err: nil},
|
{input: "123", expected: 123, err: nil},
|
||||||
{input: "abc", expected: 0, err: ErrSyntax},
|
{input: "abc", expected: 0, err: go_easy_utils.ErrSyntax},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@@ -83,13 +78,13 @@ func TestAnyToInt8(t *testing.T) {
|
|||||||
name: "positive integer out of range",
|
name: "positive integer out of range",
|
||||||
input: 128,
|
input: 128,
|
||||||
expected: 0,
|
expected: 0,
|
||||||
err: ErrValOut,
|
err: go_easy_utils.ErrValOut,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negative integer out of range",
|
name: "negative integer out of range",
|
||||||
input: -129,
|
input: -129,
|
||||||
expected: 0,
|
expected: 0,
|
||||||
err: ErrValOut,
|
err: go_easy_utils.ErrValOut,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "float",
|
name: "float",
|
||||||
@@ -107,13 +102,13 @@ func TestAnyToInt8(t *testing.T) {
|
|||||||
name: "string out of range",
|
name: "string out of range",
|
||||||
input: "128",
|
input: "128",
|
||||||
expected: 0,
|
expected: 0,
|
||||||
err: ErrValOut,
|
err: go_easy_utils.ErrValOut,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid string",
|
name: "invalid string",
|
||||||
input: "invalid",
|
input: "invalid",
|
||||||
expected: 0,
|
expected: 0,
|
||||||
err: ErrSyntax,
|
err: go_easy_utils.ErrSyntax,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +154,7 @@ func TestAnyToInt16(t *testing.T) {
|
|||||||
{float32(123.45), 123, nil},
|
{float32(123.45), 123, nil},
|
||||||
{float64(123.45), 123, nil},
|
{float64(123.45), 123, nil},
|
||||||
{"12345", 12345, nil},
|
{"12345", 12345, nil},
|
||||||
{"not a number", 0, strconv.ErrSyntax},
|
{"not a number", 0, go_easy_utils.ErrSyntax},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -183,13 +178,13 @@ func TestAnyToInt32(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{int(123), 123, nil},
|
{int(123), 123, nil},
|
||||||
{int64(2147483647), 2147483647, nil},
|
{int64(2147483647), 2147483647, nil},
|
||||||
{int64(2147483648), 0, ErrValOut},
|
{int64(2147483648), 0, go_easy_utils.ErrValOut},
|
||||||
{int64(-2147483648), -2147483648, nil},
|
{int64(-2147483648), -2147483648, nil},
|
||||||
{int64(-2147483649), 0, ErrValOut},
|
{int64(-2147483649), 0, go_easy_utils.ErrValOut},
|
||||||
{float64(123.45), 123, nil},
|
{float64(123.45), 123, nil},
|
||||||
{"123", 123, nil},
|
{"123", 123, nil},
|
||||||
{"-2147483649", 0, ErrValOut},
|
{"-2147483649", 0, go_easy_utils.ErrValOut},
|
||||||
{struct{}{}, 0, ErrType},
|
{struct{}{}, 0, go_easy_utils.ErrType},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package anyUtil
|
package anyUtil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jefferyjob/go-easy-utils"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -15,7 +16,7 @@ func AnyToUint(input interface{}) (uint, error) {
|
|||||||
|
|
||||||
// uint 兼容32位和64位系统
|
// uint 兼容32位和64位系统
|
||||||
if uint64(uint(v)) != v {
|
if uint64(uint(v)) != v {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
|
|
||||||
return uint(v), nil
|
return uint(v), nil
|
||||||
@@ -28,7 +29,7 @@ func AnyToUint8(input interface{}) (uint8, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if value > math.MaxUint8 {
|
if value > math.MaxUint8 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return uint8(value), nil
|
return uint8(value), nil
|
||||||
}
|
}
|
||||||
@@ -40,7 +41,7 @@ func AnyToUint16(input interface{}) (uint16, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if value > math.MaxUint16 {
|
if value > math.MaxUint16 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return uint16(value), nil
|
return uint16(value), nil
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ func AnyToUint32(input interface{}) (uint32, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if value > math.MaxUint32 {
|
if value > math.MaxUint32 {
|
||||||
return 0, ErrValOut
|
return 0, go_easy_utils.ErrValOut
|
||||||
}
|
}
|
||||||
return uint32(value), nil
|
return uint32(value), nil
|
||||||
}
|
}
|
||||||
@@ -65,21 +66,23 @@ func AnyToUint64(value interface{}) (uint64, error) {
|
|||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
v := reflect.ValueOf(value).Int()
|
v := reflect.ValueOf(value).Int()
|
||||||
if v < 0 {
|
if v < 0 {
|
||||||
return 0, ErrUnsignedInt
|
return 0, go_easy_utils.ErrUnsignedInt
|
||||||
}
|
}
|
||||||
return uint64(v), nil
|
return uint64(v), nil
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
v := reflect.ValueOf(value).Float()
|
v := reflect.ValueOf(value).Float()
|
||||||
if v < 0 {
|
if v < 0 {
|
||||||
return 0, ErrUnsignedInt
|
return 0, go_easy_utils.ErrUnsignedInt
|
||||||
}
|
}
|
||||||
return uint64(v), nil
|
return uint64(v), nil
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
val, err := strconv.ParseUint(value.(string), 10, 64)
|
val, err := strconv.ParseUint(value.(string), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, ErrSyntax
|
return 0, go_easy_utils.ErrSyntax
|
||||||
}
|
}
|
||||||
return val, nil
|
return val, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
return AnyToUint64(reflect.ValueOf(value).Elem().Interface())
|
||||||
}
|
}
|
||||||
return 0, ErrType
|
return 0, go_easy_utils.ErrType
|
||||||
}
|
}
|
||||||
|
@@ -1,20 +1,11 @@
|
|||||||
package anyUtil
|
package anyUtil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"github.com/jefferyjob/go-easy-utils"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAA(t *testing.T) {
|
|
||||||
toUint, err := AnyToUint(1.5)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(toUint)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAnyToUint(t *testing.T) {
|
func TestAnyToUint(t *testing.T) {
|
||||||
// Test cases
|
// Test cases
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@@ -23,7 +14,7 @@ func TestAnyToUint(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{10, 10, nil},
|
{10, 10, nil},
|
||||||
{-5, 0, ErrUnsignedInt},
|
{-5, 0, go_easy_utils.ErrUnsignedInt},
|
||||||
{"20", 20, nil},
|
{"20", 20, nil},
|
||||||
{1.5, 1, nil},
|
{1.5, 1, nil},
|
||||||
}
|
}
|
||||||
@@ -46,7 +37,7 @@ func TestAnyToUint8(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{10, 10, nil},
|
{10, 10, nil},
|
||||||
{300, 0, ErrValOut},
|
{300, 0, go_easy_utils.ErrValOut},
|
||||||
{"20", 20, nil},
|
{"20", 20, nil},
|
||||||
{1.5, 1, nil},
|
{1.5, 1, nil},
|
||||||
}
|
}
|
||||||
@@ -69,7 +60,7 @@ func TestAnyToUint16(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{10, 10, nil},
|
{10, 10, nil},
|
||||||
{70000, 0, ErrValOut},
|
{70000, 0, go_easy_utils.ErrValOut},
|
||||||
{"20", 20, nil},
|
{"20", 20, nil},
|
||||||
{1.5, 1, nil},
|
{1.5, 1, nil},
|
||||||
}
|
}
|
||||||
@@ -92,7 +83,7 @@ func TestAnyToUint32(t *testing.T) {
|
|||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{10, 10, nil},
|
{10, 10, nil},
|
||||||
{5000000000, 0, ErrValOut},
|
{5000000000, 0, go_easy_utils.ErrValOut},
|
||||||
{"20", 20, nil},
|
{"20", 20, nil},
|
||||||
{1.5, 1, nil},
|
{1.5, 1, nil},
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package anyUtil
|
package go_easy_utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
@@ -1,5 +1,21 @@
|
|||||||
# jsonUtil
|
# jsonUtil
|
||||||
|
|
||||||
|
根据结构体的字段类型和标签来自动选择将 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。如果解析失败,则返回解析错误。
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@@ -2,29 +2,13 @@ package jsonUtil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"github.com/jefferyjob/go-easy-utils"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JsonToStruct 将 JSON 字符串解析为指定的结构体指针
|
// 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 {
|
func JsonToStruct(jsonData string, result interface{}) error {
|
||||||
var data map[string]interface{}
|
var data map[string]interface{}
|
||||||
err := json.Unmarshal([]byte(jsonData), &data)
|
err := json.Unmarshal([]byte(jsonData), &data)
|
||||||
@@ -57,7 +41,7 @@ func JsonToStruct(jsonData string, result interface{}) error {
|
|||||||
|
|
||||||
switch fieldValue.Kind() {
|
switch fieldValue.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
fieldValue.SetString(value.(string))
|
fieldValue.SetString(toString(value))
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
val, err := toInt64(value)
|
val, err := toInt64(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -76,10 +60,16 @@ func JsonToStruct(jsonData string, result interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fieldValue.SetFloat(val)
|
fieldValue.SetFloat(val)
|
||||||
|
case reflect.Bool:
|
||||||
|
val := toBool(value)
|
||||||
|
fieldValue.SetBool(val)
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if subData, ok := value.(map[string]interface{}); ok {
|
if subData, ok := value.(map[string]interface{}); ok {
|
||||||
subResult := reflect.New(fieldValue.Type())
|
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())
|
fieldValue.Set(subResult.Elem())
|
||||||
}
|
}
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
@@ -92,7 +82,10 @@ func JsonToStruct(jsonData string, result interface{}) error {
|
|||||||
if subElem.Kind() == reflect.Struct {
|
if subElem.Kind() == reflect.Struct {
|
||||||
if subDataElem, ok := subValue.(map[string]interface{}); ok {
|
if subDataElem, ok := subValue.(map[string]interface{}); ok {
|
||||||
subResultElem := reflect.New(subElem.Type())
|
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())
|
subElem.Set(subResultElem.Elem())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -101,8 +94,8 @@ func JsonToStruct(jsonData string, result interface{}) error {
|
|||||||
}
|
}
|
||||||
fieldValue.Set(subResult)
|
fieldValue.Set(subResult)
|
||||||
}
|
}
|
||||||
default:
|
//default:
|
||||||
fieldValue.Set(reflect.ValueOf(value))
|
// fieldValue.Set(reflect.ValueOf(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +107,71 @@ func convertToJSONString(data map[string]interface{}) string {
|
|||||||
return string(jsonBytes)
|
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) {
|
func toInt64(value interface{}) (int64, error) {
|
||||||
|
if value == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
return int64(value.(float32)), nil
|
return int64(value.(float32)), nil
|
||||||
@@ -123,7 +180,7 @@ func toInt64(value interface{}) (int64, error) {
|
|||||||
case string:
|
case string:
|
||||||
intValue, err := strconv.ParseInt(value.(string), 10, 64)
|
intValue, err := strconv.ParseInt(value.(string), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, go_easy_utils.ErrSyntax
|
||||||
}
|
}
|
||||||
return intValue, nil
|
return intValue, nil
|
||||||
case int:
|
case int:
|
||||||
@@ -136,21 +193,35 @@ func toInt64(value interface{}) (int64, error) {
|
|||||||
return int64(value.(int32)), nil
|
return int64(value.(int32)), nil
|
||||||
case int64:
|
case int64:
|
||||||
return value.(int64), nil
|
return value.(int64), nil
|
||||||
|
case interface{}:
|
||||||
|
return 0, nil
|
||||||
default:
|
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) {
|
func toUint64(value interface{}) (uint64, error) {
|
||||||
|
if value == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
return uint64(value.(float32)), nil
|
v := value.(float32)
|
||||||
|
if v < 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return uint64(v), nil
|
||||||
case float64:
|
case float64:
|
||||||
return uint64(value.(float64)), nil
|
v := value.(float64)
|
||||||
|
if v < 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return uint64(v), nil
|
||||||
case string:
|
case string:
|
||||||
intValue, err := strconv.ParseUint(value.(string), 10, 64)
|
intValue, err := strconv.ParseUint(value.(string), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, go_easy_utils.ErrSyntax
|
||||||
}
|
}
|
||||||
return intValue, nil
|
return intValue, nil
|
||||||
case uint:
|
case uint:
|
||||||
@@ -163,22 +234,60 @@ func toUint64(value interface{}) (uint64, error) {
|
|||||||
return uint64(value.(uint32)), nil
|
return uint64(value.(uint32)), nil
|
||||||
case uint64:
|
case uint64:
|
||||||
return value.(uint64), nil
|
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:
|
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) {
|
func toFloat64(value interface{}) (float64, error) {
|
||||||
|
if value == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
|
case float32:
|
||||||
|
return float64(value.(float32)), nil
|
||||||
case float64:
|
case float64:
|
||||||
return value.(float64), nil
|
return value.(float64), nil
|
||||||
case string:
|
case string:
|
||||||
floatValue, err := strconv.ParseFloat(value.(string), 64)
|
floatValue, err := strconv.ParseFloat(value.(string), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, go_easy_utils.ErrSyntax
|
||||||
}
|
}
|
||||||
return floatValue, nil
|
return floatValue, nil
|
||||||
default:
|
default:
|
||||||
return 0, errors.New(fmt.Sprintf("jsonUtils toFloat64 err: %T \n", value))
|
return 0, go_easy_utils.ErrType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -106,6 +106,21 @@ func TestJsonToStruct2(t *testing.T) {
|
|||||||
|
|
||||||
fmt.Printf("person1:%+v \n", person1)
|
fmt.Printf("person1:%+v \n", person1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJsonToStruct3(t *testing.T) {
|
||||||
|
type Address struct {
|
||||||
|
City string `json:"city"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Address Address `json:"address"`
|
||||||
|
Interests []string `json:"interests"`
|
||||||
|
}
|
||||||
|
|
||||||
jsonData2 := `{
|
jsonData2 := `{
|
||||||
"name": "Bob",
|
"name": "Bob",
|
||||||
"age": "25",
|
"age": "25",
|
||||||
@@ -117,7 +132,7 @@ func TestJsonToStruct2(t *testing.T) {
|
|||||||
}`
|
}`
|
||||||
|
|
||||||
var person2 Person
|
var person2 Person
|
||||||
err = JsonToStruct(jsonData2, &person2)
|
err := JsonToStruct(jsonData2, &person2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -126,7 +141,7 @@ func TestJsonToStruct2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 多层级json测试
|
// 多层级json测试
|
||||||
func TestJsonToStruct3(t *testing.T) {
|
func TestJsonToStruct4(t *testing.T) {
|
||||||
type Address struct {
|
type Address struct {
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
Street string `json:"street"`
|
Street string `json:"street"`
|
||||||
@@ -166,3 +181,68 @@ func TestJsonToStruct3(t *testing.T) {
|
|||||||
|
|
||||||
fmt.Printf("%+v \n", student)
|
fmt.Printf("%+v \n", student)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJsonToStruct5(t *testing.T) {
|
||||||
|
type Student struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Age int `json:"age,omitempty"`
|
||||||
|
}
|
||||||
|
jsonStr4 := `{
|
||||||
|
"name":null,
|
||||||
|
"age": "30"
|
||||||
|
}`
|
||||||
|
|
||||||
|
var student Student
|
||||||
|
if err := JsonToStruct(jsonStr4, &student); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%+v \n", student)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJsonToStruct6(t *testing.T) {
|
||||||
|
type Student struct {
|
||||||
|
Name interface{} `json:"name,omitempty"`
|
||||||
|
Age int `json:"age,omitempty"`
|
||||||
|
}
|
||||||
|
jsonStr4 := `{
|
||||||
|
"name":"zhangsan",
|
||||||
|
"age": "123"
|
||||||
|
}`
|
||||||
|
|
||||||
|
var student Student
|
||||||
|
if err := JsonToStruct(jsonStr4, &student); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%+v \n", student)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJsonToStruct7(t *testing.T) {
|
||||||
|
type Student struct {
|
||||||
|
Name bool `json:"name"`
|
||||||
|
Name2 uint `json:"name2"`
|
||||||
|
Name3 uint `json:"name3"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
}
|
||||||
|
jsonStr4 := `{
|
||||||
|
"name": true,
|
||||||
|
"name2": -1,
|
||||||
|
"name3": null,
|
||||||
|
"age": "123"
|
||||||
|
}`
|
||||||
|
|
||||||
|
var student Student
|
||||||
|
if err := JsonToStruct(jsonStr4, &student); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%#v \n", student)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToUint64(t *testing.T) {
|
||||||
|
fmt.Println(toUint64(""))
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user