Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding nested tags for slice of strings #49

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions example_nested_tags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package faker_test

import (
"fmt"
"regexp"
"testing"
"unicode/utf8"

"github.com/go-faker/faker/v4"
)

type StructWithNestedTags struct {
ListEmail []string `faker:"[email]"`
ListUrisWithLength []string `faker:"slice_len=3, [url]"`
ListWordWithLang []string `faker:"slice_len=4, [word lang=kor]"`
// ListNumsOneOf []float64 `faker:"[oneof: 3928.8383 83.837387]"`
}

func Example_withNestedTags() {
a := &StructWithNestedTags{}
_ = faker.FakeData(&a)
fmt.Printf("%+v", a)
// Result:
/*
{
ListEmail:[
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
]
ListUrisWithLength:[
https://zzshyph.top/LiMcQyr.html
https://hdjxcmb.biz/BOSXMvB.jpg
http://yllwaiu.org/
]
ListWordWithLang:[
냶싹푣이솠휑넹뤭쾅쳎숩뎷쀷젆뉄쯃콅롾촸콝뉉똇쪈묒놬
땭뚪휪뉯묽쫣둴뜢튔뻴쒿쬭쒃쐓멪펧뵼왌쵢뚰옐첋똠갬둎
늒띻붬툮휣쒗쏦뙀셨쿫쎦뤿픓삠숊막뾰욤뾃쁂뼉륍펜툅샶
샾족쭪낪챗엩바쇒뜇턝돁쏸봕맛뜼퐉뱌횋틖뫁뗽룋왙읠왂
]
}
*/
}

func Test_withNestedTags(t *testing.T) {
a := &StructWithNestedTags{}

err := faker.FakeData(&a)

if err != nil {
t.Errorf("want %v, got %v", nil, err)
}

if len(a.ListEmail) < 1 {
t.Errorf("Empty email list")
}

for _, e := range a.ListEmail {
if m, _ := regexp.MatchString("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-z]{2,3}", e); !m {

Check failure on line 85 in example_nested_tags_test.go

View workflow job for this annotation

GitHub Actions / build

SA6000: calling regexp.MatchString in a loop has poor performance, consider using regexp.Compile (staticcheck)
t.Errorf("Invalid email generated %s", e)
break
}
}

if len(a.ListUrisWithLength) != 3 {
t.Errorf("Expected list of length %d, got length %d", 3, len(a.ListUrisWithLength))
}

for _, e := range a.ListUrisWithLength {
if m, _ := regexp.MatchString("(https?://)?.+\\.[a-zA-Z0-9]{2,4}", e); !m {

Check failure on line 96 in example_nested_tags_test.go

View workflow job for this annotation

GitHub Actions / build

SA6000: calling regexp.MatchString in a loop has poor performance, consider using regexp.Compile (staticcheck)
t.Errorf("Invalid uri format generated %s", e)
break
}
}

if len(a.ListWordWithLang) != 4 {
t.Errorf("Expected list of length %d, got length %d", 4, len(a.ListWordWithLang))
}

for _, e := range a.ListWordWithLang {
if len(e) == utf8.RuneCountInString(e) {
t.Errorf("String and rune of same length (%d)", len(e))
break
}
}
}
45 changes: 36 additions & 9 deletions faker.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,11 @@ func initMappertTagDefault() {

// Compiled regexp
var (
findLangReg *regexp.Regexp
findLenReg *regexp.Regexp
findSliceLenReg *regexp.Regexp
findLangReg *regexp.Regexp
findLenReg *regexp.Regexp
findSliceLenReg *regexp.Regexp
matchInnerTagsReg *regexp.Regexp
findInnerTagsReg *regexp.Regexp
)

func init() {
Expand All @@ -251,6 +253,8 @@ func init() {
findLangReg, _ = regexp.Compile("lang=[a-z]{3}")
findLenReg, _ = regexp.Compile(`len=\d+`)
findSliceLenReg, _ = regexp.Compile(`slice_len=\d+`)
matchInnerTagsReg, _ = regexp.Compile(`^\s?\[.+\]\s?$`) // Regex to check if tag contains nested tags
findInnerTagsReg, _ = regexp.Compile(`\[(.+)\]`) // Regex to find nested tags

randNameFlag = rand.Intn(100) // for person
}
Expand Down Expand Up @@ -673,6 +677,12 @@ func decodeTags(typ reflect.Type, i int, tagName string) structTag {
delete(pMap, ptag)
}
}
// Nested
for _, tag := range pMap {
if matchInnerTagsReg.MatchString(tag) {
res = append(res, tag)
}
}
// custom,keep,unique
if len(res) < 1 {
if !keepOriginal && !uni {
Expand Down Expand Up @@ -879,8 +889,16 @@ func userDefinedArray(v reflect.Value, tag string, opt options.Options) error {
v.Set(reflect.Zero(v.Type()))
return nil
}
//remove slice_len from tag string to avoid extra logic in downstream function
tag = findSliceLenReg.ReplaceAllString(tag, "")

subMatch := findInnerTagsReg.FindAllStringSubmatch(tag, -1)
if len(subMatch) == 1 && len(subMatch[0]) == 2 {
// Remove all tags except nested tags
tag = subMatch[0][1]
} else {
//remove slice_len from tag string to avoid extra logic in downstream function
tag = findSliceLenReg.ReplaceAllString(tag, "")
}

array := reflect.MakeSlice(v.Type(), sliceLen, sliceLen)
for i := 0; i < array.Len(); i++ {
k := v.Type().Elem().Kind()
Expand All @@ -904,11 +922,20 @@ func userDefinedArray(v reflect.Value, tag string, opt options.Options) error {
continue
}

res, err := getValueWithTag(v.Type().Elem(), tag, opt)
if err != nil {
return err
// Check and load tag function for nested tags
if tagFunc, ok := mapperTag.Load(tag); ok {
res, err := tagFunc(v)
if err != nil {
return err
}
array.Index(i).Set(reflect.ValueOf(res))
} else {
res, err := getValueWithTag(v.Type().Elem(), tag, opt)
if err != nil {
return err
}
array.Index(i).Set(reflect.ValueOf(res))
}
array.Index(i).Set(reflect.ValueOf(res))
}
v.Set(array)
return nil
Expand Down
Loading