Skip to content

Commit 9c3238c

Browse files
committed
update:全面支持泛型,支持go1.18 添加案例,修复omit解析时字段未写json标签被忽略的bug
1 parent 773e00e commit 9c3238c

11 files changed

+414
-22
lines changed

README.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
## English
99

10-
Golang's JSON field filter can select fields at will, output fields of specified structures at will, and reuse structures.
10+
Golang's JSON field filter can select fields at will, output fields of specified structures at will, and reuse structures. **It fully supports generics** and is perfectly compatible with go 1.18 and 1.17 and below
1111

1212
list:
1313

@@ -277,13 +277,13 @@ func main() {
277277
},
278278
}
279279

280-
fmt.Println(filter.SelectMarshal("justName", tags))
280+
fmt.Println(filter.SelectMarshal("justName", tags).MustJSON())
281281
//--->output: [{"name":"c"},{"name":"c++"},{"name":"go"}]
282282

283-
fmt.Println(filter.SelectMarshal("all", tags))
283+
fmt.Println(filter.SelectMarshal("all", tags).MustJSON())
284284
//--->output: [{"icon":"icon-c","id":1,"name":"c"},{"icon":"icon-c++","id":1,"name":"c++"},{"icon":"icon-go","id":1,"name":"go"}]
285285

286-
fmt.Println(filter.SelectMarshal("chat", tags))
286+
fmt.Println(filter.SelectMarshal("chat", tags).MustJSON())
287287
//--->output: [{"icon":"icon-c"},{"icon":"icon-c++"},{"icon":"icon-go"}]
288288

289289
}
@@ -321,7 +321,7 @@ func main() {
321321
},
322322
}
323323

324-
articleJson := filter.SelectMarshal("article", article)
324+
articleJson := filter.SelectMarshal("article", article).MustJSON()
325325
fmt.Println(articleJson)
326326
//output---> {"pageInfo":999,"pageNum":1,"title":"c++从研发到脱发"}
327327
}
@@ -434,7 +434,7 @@ func main() {
434434

435435
// If I only want to add some user information related to the programming language
436436
lang := filter.SelectMarshal("lang", user)
437-
fmt.Println(lang)
437+
fmt.Println(lang.MustJSON())
438438
//{"langAge":[{"name":"c"},{"name":"c++"},{"name":"Go"}],"uid":1}
439439

440440
//format
@@ -455,7 +455,7 @@ func main() {
455455

456456
//If I just want to get some field information of uid and all arts under langage, you can do this
457457
lookup := filter.SelectMarshal("lookup", user)
458-
fmt.Println(lookup)
458+
fmt.Println(lookup.MustJSON())
459459
//{"langAge":[{"arts":[{"profile":{"c":"clang"},"values":["1","2"]}]},{"arts":[{"profile":{"c++":"cpp"},"values":["cpp1","cpp2"]}]},{"arts":[{"profile":{"Golang":"go"},"values":["Golang","Golang1"]}]}],"uid":1}
460460

461461

@@ -626,7 +626,7 @@ func UserRes(c *gin.Context) {
626626

627627
### 简体中文
628628

629-
golang的json字段过滤器,随意选择字段,随意输出指定结构体的字段,复用结构体。
629+
golang的json字段过滤器,随意选择字段,随意输出指定结构体的字段,复用结构体**全面支持泛型**,对于go 1.18和1.17及其以下版本完美兼容
630630

631631
视频教程快速入门:https://www.bilibili.com/video/BV1ba411b7m1/
632632

@@ -901,13 +901,13 @@ func main() {
901901
},
902902
}
903903

904-
fmt.Println(filter.SelectMarshal("justName", tags))
904+
fmt.Println(filter.SelectMarshal("justName", tags).MustJSON())
905905
//--->输出结果: [{"name":"c"},{"name":"c++"},{"name":"go"}]
906906

907-
fmt.Println(filter.SelectMarshal("all", tags))
907+
fmt.Println(filter.SelectMarshal("all", tags).MustJSON())
908908
//--->输出结果: [{"icon":"icon-c","id":1,"name":"c"},{"icon":"icon-c++","id":1,"name":"c++"},{"icon":"icon-go","id":1,"name":"go"}]
909909

910-
fmt.Println(filter.SelectMarshal("chat", tags))
910+
fmt.Println(filter.SelectMarshal("chat", tags).MustJSON())
911911
//--->输出结果: [{"icon":"icon-c"},{"icon":"icon-c++"},{"icon":"icon-go"}]
912912

913913
}
@@ -948,7 +948,7 @@ func main() {
948948
},
949949
}
950950

951-
articleJson := filter.SelectMarshal("article", article)
951+
articleJson := filter.SelectMarshal("article", article).MustJSON()
952952
fmt.Println(articleJson)
953953
//输出结果---> {"pageInfo":999,"pageNum":1,"title":"c++从研发到脱发"}
954954
}
@@ -1062,7 +1062,7 @@ func main() {
10621062

10631063
// 如果我只想要编程语言相关加上部分用户信息的话
10641064
lang := filter.SelectMarshal("lang", user)
1065-
fmt.Println(lang)
1065+
fmt.Println(lang.MustJSON())
10661066
//{"langAge":[{"name":"c"},{"name":"c++"},{"name":"Go"}],"uid":1}
10671067

10681068
//格式化后
@@ -1083,7 +1083,7 @@ func main() {
10831083

10841084
//如果我只是想获取uid加上langAge下所有Art的部分字段信息, 你可以这样
10851085
lookup := filter.SelectMarshal("lookup", user)
1086-
fmt.Println(lookup)
1086+
fmt.Println(lookup.MustJSON())
10871087
//{"langAge":[{"arts":[{"profile":{"c":"clang"},"values":["1","2"]}]},{"arts":[{"profile":{"c++":"cpp"},"values":["cpp1","cpp2"]}]},{"arts":[{"profile":{"Golang":"go"},"values":["Golang","Golang1"]}]}],"uid":1}
10881088

10891089

example/anonymous_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/liu-cn/json-filter/filter"
6+
"testing"
7+
)
8+
9+
func TestAnonymous(t *testing.T) {
10+
11+
type Page struct {
12+
PageInfo int `json:"pageInfo,select($any)"`
13+
PageNum int `json:"pageNum,select($any)"`
14+
}
15+
16+
type Article struct {
17+
Title string `json:"title,select(article)"`
18+
Page `json:",select(article)"` // 这种tag字段名为空的方式会直接把该结构体展开,当作匿名结构体处理
19+
//Page `json:"page,select(article)"` // 注意这里tag里标注了匿名结构体的字段名,所以解析时会解析成对象,不会展开
20+
Author string `json:"author,select(admin)"`
21+
}
22+
23+
article := Article{
24+
Title: "c++从研发到脱发",
25+
Page: Page{
26+
PageInfo: 999,
27+
PageNum: 1,
28+
},
29+
}
30+
31+
articleJson := filter.SelectMarshal("article", article)
32+
fmt.Println(articleJson.MustJSON())
33+
//输出结果---> {"pageInfo":999,"pageNum":1,"title":"c++从研发到脱发"}
34+
35+
}

example/complex_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/liu-cn/json-filter/filter"
6+
"testing"
7+
)
8+
9+
type Users struct {
10+
UID uint `json:"uid,select($any)"`
11+
Name string `json:"name,select(comment|chat|profile|justName)"`
12+
Age int `json:"age,select(comment|chat|profile)"`
13+
Avatar string `json:"avatar,select(comment|chat|profile)"`
14+
Birthday int `json:"birthday,select(profile)"`
15+
Password string `json:"password"`
16+
PasswordSlat string `json:"password_slat"`
17+
LangAge []Lang `json:"langAge,select(profile|lookup|lang)"`
18+
}
19+
20+
type Lang struct {
21+
Name string `json:"name,select(profile|lang)"`
22+
Arts []*Art `json:"arts,select(profile|lookup)"`
23+
}
24+
25+
type Art struct {
26+
Name string `json:"name,select(profile)"`
27+
Profile map[string]interface{} `json:"profile,select(profile|lookup)"`
28+
Values []string `json:"values,select(profile|lookup)"`
29+
}
30+
31+
func NewUser() Users {
32+
return Users{
33+
UID: 1,
34+
Name: "boyan",
35+
Age: 20,
36+
Avatar: "https://www.avatar.com",
37+
Birthday: 2001,
38+
PasswordSlat: "slat",
39+
Password: "123",
40+
LangAge: []Lang{
41+
{
42+
Name: "c",
43+
Arts: []*Art{
44+
{
45+
Name: "cc",
46+
Profile: map[string]interface{}{
47+
"c": "clang",
48+
},
49+
Values: []string{"1", "2"},
50+
},
51+
},
52+
},
53+
{
54+
Name: "c++",
55+
Arts: []*Art{
56+
{
57+
Name: "c++",
58+
Profile: map[string]interface{}{
59+
"c++": "cpp",
60+
},
61+
Values: []string{"cpp1", "cpp2"},
62+
},
63+
},
64+
},
65+
{
66+
Name: "Go",
67+
Arts: []*Art{
68+
{
69+
Name: "Golang",
70+
Profile: map[string]interface{}{
71+
"Golang": "go",
72+
},
73+
Values: []string{"Golang", "Golang1"},
74+
},
75+
},
76+
},
77+
},
78+
}
79+
}
80+
81+
func TestComplex(t *testing.T) {
82+
user := NewUser()
83+
lang := filter.SelectMarshal("lang", user)
84+
fmt.Println(lang.MustJSON())
85+
//{"langAge":[{"name":"c"},{"name":"c++"},{"name":"Go"}],"uid":1}
86+
87+
lookup := filter.SelectMarshal("lookup", user)
88+
fmt.Println(lookup.MustJSON())
89+
//{"langAge":[{"arts":[{"profile":{"c":"clang"},"values":["1","2"]}]},{"arts":[{"profile":{"c++":"cpp"},"values":["cpp1","cpp2"]}]},{"arts":[{"profile":{"Golang":"go"},"values":["Golang","Golang1"]}]}],"uid":1}
90+
91+
}

example/generic.go.exam

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package test
2+
3+
import (
4+
"fmt"
5+
"github.com/liu-cn/json-filter/filter"
6+
"testing"
7+
)
8+
9+
10+
11+
//完全兼容泛型,
12+
//Fully compatible generics
13+
14+
15+
16+
type Lang struct {
17+
Name string `json:"name,select(article)"`
18+
IsStatic bool `json:"is_static,select(article)"`
19+
}
20+
21+
type User[T, K, V any] struct {
22+
Nickname string `json:"nickname,select(article|chat)"`
23+
24+
Data T `json:"data,select(article)"`
25+
Data1 *T `json:"data1,select(article)"`
26+
27+
K K `json:"k,select(article)"`
28+
KP *K `json:"k_p,select(article)"`
29+
V V `json:"v,select(article)"`
30+
VP *V `json:"vp,select(article)"`
31+
}
32+
33+
func NewUser() User[Lang, string, int] {
34+
k := "key"
35+
v := 10
36+
return User[Lang, string, int]{
37+
Nickname: "boyan",
38+
Data: Lang{
39+
Name: "go",
40+
IsStatic: true,
41+
},
42+
Data1: &Lang{
43+
Name: "c++",
44+
IsStatic: true,
45+
},
46+
K: k,
47+
KP: &k,
48+
V: v,
49+
VP: &v,
50+
}
51+
}
52+
53+
func TestJson(t *testing.T) {
54+
fmt.Println(filter.SelectMarshal("article", NewUser()).MustJSON())
55+
//{"data":{"is_static":true,"name":"go"},"data1":{"is_static":true,"name":"c++"},"k":"key","k_p":"key","nickname":"boyan","v":10,"vp":10}
56+
57+
58+
fmt.Println(filter.SelectMarshal("chat", NewUser()).MustJSON())
59+
//{"nickname":"boyan"}
60+
}

example/good_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import "github.com/liu-cn/json-filter/filter"
4+
5+
type UserModel struct {
6+
UID uint `json:"uid,select($any)"` //标记了$any无论选择任何场景都会解析该参数
7+
Name string `json:"name,select(article|profile|chat)"`
8+
Avatar interface{} `json:"data,select(profile|chat)"`
9+
}
10+
11+
func (u UserModel) ArticleResp() interface{} {
12+
//这样当你后面想要优化性能时可以在这里进行优化,
13+
return filter.SelectMarshal("article", u).Interface()
14+
}
15+
16+
func (u UserModel) ProfileResp() interface{} {
17+
//这样当你后面想要优化性能时可以在这里进行优化,
18+
return filter.SelectMarshal("profile", u).Interface()
19+
}
20+
21+
func (u UserModel) ChatResp() interface{} {
22+
//假如性能出现瓶颈,想要优化
23+
chat := struct {
24+
UID uint `json:"uid"`
25+
Name string `json:"name"`
26+
}{
27+
UID: u.UID,
28+
Name: u.Name,
29+
}
30+
return chat
31+
}

example/omit_simple_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/liu-cn/json-filter/filter"
6+
"testing"
7+
)
8+
9+
type OmitUser struct {
10+
Name string
11+
Avatar string `json:"avatar,omit(lang)"`
12+
LangAge LangAger
13+
}
14+
15+
type LangAger struct {
16+
Name string
17+
IsStatic bool `json:"is_static,omit(lang)"`
18+
}
19+
20+
func NewOmitUser() OmitUser {
21+
return OmitUser{
22+
Name: "boyan",
23+
Avatar: "avatar111",
24+
LangAge: LangAger{
25+
Name: "go",
26+
IsStatic: true,
27+
},
28+
}
29+
}
30+
31+
func TestOmitUser(t *testing.T) {
32+
fmt.Println(filter.OmitMarshal("lang", NewOmitUser()).MustJSON())
33+
//{"LangAge":{"Name":"go"},"Name":"boyan"}
34+
}

example/select_omit_any_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/liu-cn/json-filter/filter"
6+
"testing"
7+
)
8+
9+
type Anyway struct {
10+
Name string `json:"name,select($any),omit(user)"`
11+
Age int `json:"age,select(chat),omit(profile)"`
12+
Sex int `json:"sex,select(article),omit($any)"`
13+
}
14+
15+
func newAnyway() Anyway {
16+
return Anyway{
17+
Age: 10,
18+
Sex: 10,
19+
Name: "boyan",
20+
}
21+
}
22+
23+
func TestSelectAny(t *testing.T) {
24+
fmt.Println(filter.SelectMarshal("chat", newAnyway()).MustJSON())
25+
//{"age":10,"name":"boyan"}
26+
fmt.Println(filter.SelectMarshal("article", newAnyway()).MustJSON())
27+
//{"name":"boyan","sex":10}
28+
}
29+
30+
func TestOmitAny(t *testing.T) {
31+
fmt.Println(filter.OmitMarshal("user", newAnyway()).MustJSON())
32+
//{"age":10}
33+
fmt.Println(filter.OmitMarshal("profile", newAnyway()).MustJSON())
34+
//{"name":"boyan"}
35+
}

0 commit comments

Comments
 (0)