Files
go-easy-utils/jsonx/to_struct_test.go
2025-07-08 15:26:54 +08:00

630 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package jsonx
import (
"encoding/json"
"fmt"
"reflect"
"testing"
)
// name uses two json tags
// age is defined as int, and the value of json is string
// is_use is defined as bool, the value of json is int
func TestDemo1(t *testing.T) {
jsonData := `{
"name": "make",
"age": "22",
"is_use": "1"
}`
var people struct {
Name string `json:"name,omitempty"`
Age int `json:"age"`
IsUse bool `json:"is_use"`
}
if err := ToStruct(jsonData, &people); err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v \n", people)
// return
// {Name:make Age:22 IsUse:true}
}
// Structure nesting and slice nesting processing
func TestJsonToStructDemo2(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 := `{
"name": "Bob",
"age": "25",
"address": {
"city": "Shanghai",
"country": "China"
},
"interests": ["reading", "swimming"]
}`
var person Person
err := ToStruct(jsonData2, &person)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v \n", person)
// {Name:Bob Age:25 Address:{City:Shanghai Country:China} Interests:[reading swimming]}
}
func BenchmarkJsonUnmarshal(b *testing.B) {
jsonData := `{
"name": "make",
"age": 22,
"is_use": true
}`
var people struct {
Name string `json:"name,omitempty"`
Age int `json:"age"`
IsUse bool `json:"is_use"`
}
for i := 0; i < b.N; i++ {
err := json.Unmarshal([]byte(jsonData), &people)
if err != nil {
fmt.Println("err:", err)
return
}
}
}
func BenchmarkJsonToStruct(b *testing.B) {
jsonData := `{
"name": "make",
"age": "22",
"is_use": true
}`
var people struct {
Name string `json:"name,omitempty"`
Age int `json:"age"`
IsUse bool `json:"is_use"`
}
for i := 0; i < b.N; i++ {
err := ToStruct(jsonData, &people)
if err != nil {
fmt.Println("err:", err)
return
}
}
}
// 非法验证非法的json字符串
func TestJsonToStructErrJson(t *testing.T) {
jsonData := `{"name":}`
type People struct {
Name string `json:"name"`
}
var people People
err := ToStruct(jsonData, &people)
if err == nil {
t.Errorf("err %s", err)
return
}
}
// 非法验证非指针的result
func TestJsonToStructErrResult(t *testing.T) {
jsonData := `{
"name": "make",
"age": "22",
"is_use": "1"
}`
var people struct {
Name string `json:"name,omitempty"`
Age int `json:"age"`
IsUse bool `json:"is_use"`
}
err := ToStruct(jsonData, people)
if err == nil {
t.Errorf("err %s", err)
return
}
}
// 合法验证:空数据
func TestJsonToStructEmptyValue(t *testing.T) {
jsonData := `{
"name": "make",
"age": "",
"source": "",
"num": "",
"status": ""
}`
var people struct {
Name string `json:"name,omitempty"`
Age int `json:"age"`
Source uint `json:"source"`
Num float64 `json:"num"`
Status bool `json:"status"`
}
err := ToStruct(jsonData, &people)
if err != nil {
t.Errorf("err %s", err)
return
}
}
// 非法验证非法的int
func TestJsonToStructErrInt(t *testing.T) {
jsonData := `{
"name": "make",
"age": "test abc"
}`
var people struct {
Name string `json:"name,omitempty"`
Age int `json:"age"`
}
err := ToStruct(jsonData, people)
if err == nil {
t.Errorf("err %s", err)
return
}
}
// 非法验证非法的uint
func TestJsonToStructErrUint(t *testing.T) {
jsonData := `{
"name": "make",
"age": "test abc"
}`
var people struct {
Name string `json:"name,omitempty"`
Age uint `json:"age"`
}
err := ToStruct(jsonData, people)
if err == nil {
t.Errorf("err %s", err)
return
}
}
// 非法验证非法的float
func TestJsonToStructErrFloat(t *testing.T) {
jsonData := `{
"name": "make",
"age": "test abc"
}`
var people struct {
Name string `json:"name,omitempty"`
Age float64 `json:"age"`
}
err := ToStruct(jsonData, people)
if err == nil {
t.Errorf("err %s", err)
return
}
}
// 非法验证:嵌套的数据类型错误
func TestJsonToStructNestErrInt(t *testing.T) {
jsonData := `{
"name": "John Doe",
"address": {
"number": "test abc"
}
}`
type Address struct {
Number int `json:"number"`
}
type Person struct {
Name string `json:"name"`
Address Address `json:"address"`
}
people := &Person{}
err := ToStruct(jsonData, people)
if err == nil {
t.Errorf("err %s", err)
return
}
}
// 合法验证:多层级嵌套
func TestJsonToStructMoreNest(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"`
Source float64 `json:"source"`
Number int `json:"number"`
Status bool `json:"status"`
Address Address `json:"address"`
Emails []string `json:"emails"`
}
jsonData := `{
"name": "John Doe",
"age": 30,
"source": "99.99",
"status": true,
"address": {
"city": "Shanghai",
"country": "China"
},
"emails": [
"john.doe@example.com",
"jdoe@example.com"
]
}`
expectedPerson := Person{
Name: "John Doe",
Age: 30,
Status: true,
Address: Address{
City: "Shanghai",
Country: "China",
},
Emails: []string{"john.doe@example.com", "jdoe@example.com"},
}
var resultPerson Person
err := ToStruct(jsonData, &resultPerson)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if resultPerson.Name != expectedPerson.Name {
t.Errorf("Name field mismatch: expected %s but got %s", expectedPerson.Name, resultPerson.Name)
}
if resultPerson.Age != expectedPerson.Age {
t.Errorf("Age field mismatch: expected %d but got %d", expectedPerson.Age, resultPerson.Age)
}
if resultPerson.Status != expectedPerson.Status {
t.Errorf("Status field mismatch: expected %v but got %v", expectedPerson.Status, resultPerson.Status)
}
if resultPerson.Address.City != expectedPerson.Address.City {
t.Errorf("Address.City field mismatch: expected %s but got %s", expectedPerson.Address.City, resultPerson.Address.City)
}
if resultPerson.Address.Country != expectedPerson.Address.Country {
t.Errorf("Address.Country field mismatch: expected %s but got %s", expectedPerson.Address.Country, resultPerson.Address.Country)
}
if len(resultPerson.Emails) != len(expectedPerson.Emails) {
t.Errorf("Emails length mismatch: expected %d but got %d", len(expectedPerson.Emails), len(resultPerson.Emails))
}
for i, expectedEmail := range expectedPerson.Emails {
if resultPerson.Emails[i] != expectedEmail {
t.Errorf("Emails[%d] mismatch: expected %s but got %s", i, expectedEmail, resultPerson.Emails[i])
}
}
}
// 合法验证:多层级嵌套
func TestJsonToStructMoreNest2(t *testing.T) {
var jsonData = `
{
"uid": 666,
"use_id": ["hello", 5, 9],
"age": "20",
"equip": {
"keyMike": true,
"keyTom": false
},
"happy": {
"k1": [1, 2, 3],
"k2": [4, 5, 6]
},
"slices": [{
"nickname": "ABC",
"money": "20"
}, {
"nickname": "EFG",
"money": "22"
}],
"maps": {
"m1": {
"name": "alis",
"age": "20"
},
"m2": {
"name": "jom",
"age": "22"
}
}
}
`
type SliceVal struct {
Nickname string `json:"nickname"`
Money int `json:"money"`
}
type MapVal struct {
Name string `json:"name"`
Age int `json:"age"`
}
type Target struct {
Uid int `json:"uid"`
UseId []string `json:"use_id"`
Age int `json:"age"`
Equip map[string]bool `json:"equip"`
Happy map[string][]int `json:"happy"`
Slices []SliceVal `json:"slices"`
Maps map[string]MapVal `json:"maps"`
}
var res Target
err := ToStruct(jsonData, &res)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
// jsonRes, _ := json.Marshal(res)
// fmt.Printf("%+v \n", res)
// fmt.Println(string(jsonRes))
expected := Target{
Uid: 666,
UseId: []string{"hello", "5", "9"},
Age: 20,
Equip: map[string]bool{
"keyMike": true,
"keyTom": false,
},
Happy: map[string][]int{
"k1": {1, 2, 3},
"k2": {4, 5, 6},
},
Slices: []SliceVal{
{
Nickname: "ABC",
Money: 20,
},
{
Nickname: "EFG",
Money: 22,
},
},
Maps: map[string]MapVal{
"m1": {
Name: "alis",
Age: 20,
},
"m2": {
Name: "jom",
Age: 22,
},
},
}
if !reflect.DeepEqual(res, expected) {
t.Errorf("Result not as expected.\nExpected: %+v\nActual: %+v\n", expected, res)
}
}
// 普通数据类型定义 interface
func TestJsonToStructAny1(t *testing.T) {
jsonData := `{
"name": "make",
"age": "10"
}`
type Target struct {
Name interface{} `json:"name"`
Age uint `json:"age"`
}
var target Target
err := ToStruct(jsonData, &target)
if err != nil {
t.Errorf("err %s", err)
return
}
}
// 普通数据类型定义 any
func TestJsonToStructAny2(t *testing.T) {
jsonData := `{
"name": "make",
"age": "10"
}`
type Target struct {
Name any `json:"name"`
Age uint `json:"age"`
}
var target Target
err := ToStruct(jsonData, &target)
if err != nil {
t.Errorf("err %s", err)
return
}
}
// slice 中包含 interface
func TestJsonToStructAny3(t *testing.T) {
jsonData := `{
"name": ["make",6,"tom"]
}`
type Target struct {
Name []interface{} `json:"name"`
}
var target Target
err := ToStruct(jsonData, &target)
if err != nil {
t.Errorf("err %s", err)
return
}
}
// slice 中包含 any
func TestJsonToStructAny4(t *testing.T) {
jsonData := `{
"name": ["make",6,"tom"]
}`
type Target struct {
Name []any `json:"name"`
}
var target Target
err := ToStruct(jsonData, &target)
if err != nil {
t.Errorf("err %s", err)
return
}
fmt.Println(target, err)
}
// map 中包含 interface
func TestJsonToStructAny5(t *testing.T) {
jsonData := `{
"name": {
"key1": "mike",
"key2": 666
}
}`
type Target struct {
Name map[string]interface{} `json:"name"`
}
var target Target
err := ToStruct(jsonData, &target)
if err != nil {
t.Errorf("err %s", err)
return
}
}
// map 中包含 any
func TestJsonToStructAny6(t *testing.T) {
jsonData := `{
"name": {
"key1": "mike",
"key2": 666
}
}`
type Target struct {
Name map[string]any `json:"name"`
}
var target Target
err := ToStruct(jsonData, &target)
if err != nil {
t.Errorf("err %s", err)
return
}
}
// 多层级json测试
// func TestJsonToStruct4(t *testing.T) {
// type Address struct {
// City string `json:"city"`
// Street string `json:"street"`
// Zipcode uint64 `json:"zipcode"`
// }
//
// type Score struct {
// Subject string `json:"subject"`
// Score int `json:"score"`
// }
//
// type Student struct {
// Name string `json:"name,omitempty"`
// Age int `json:"age,omitempty"`
// Address Address `json:"address"`
// Scores []Score `json:"scores,omitempty"`
// }
// jsonStr4 := `{
// "name": "Alice",
// "age": 30,
// "address": {
// "city": "Beijing",
// "street": "Zhangsan Street",
// "zipcode": 100
// },
// "scores": [
// {"subject": "Math", "score": 80},
// {"subject": "English", "score": 90}
// ]
// }`
//
// var student Student
// if err := JsonToStruct(jsonStr4, &student); err != nil {
// fmt.Println(err)
// return
// }
//
// 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 any `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)
// }