2 files changed,
43 insertions(+),
9 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2025-11-26 20:05:07 +0200
Authored at:
2025-11-26 19:50:22 +0200
Change ID:
nxznoqyxnmxwnuxnkzruyrvvptxluuwn
Parent:
7a527f3
jump to
| M | json2go.go |
| M | json2go_test.go |
M
json2go.go
··· 4 4 "encoding/json" 5 5 "errors" 6 6 "fmt" 7 + "regexp" 7 8 "sort" 8 9 "strings" 9 10 ) 10 11 11 -var ErrInvalidJSON = errors.New("invalid json") 12 +var identRe = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) 13 +var ( 14 + ErrInvalidJSON = errors.New("invalid json") 15 + ErrInvalidStructName = errors.New("invalid struct name") 16 +) 12 17 13 18 type Transformer struct { 14 19 structName string ··· 21 26 // Transform ... 22 27 // todo: take io.Reader as input? 23 28 // todo: output as io.Writer? 24 -// todo: validate provided structName 25 29 func (t *Transformer) Transform(structName, jsonStr string) (string, error) { 30 + if !identRe.MatchString(structName) { 31 + return "", ErrInvalidStructName 32 + } 33 + 26 34 t.structName = structName 27 35 28 36 var input any ··· 65 73 } 66 74 } 67 75 68 -// todo: input shouldn't be map, to preserve it's order 69 76 func (t *Transformer) buildStruct(input map[string]any) string { 70 77 var fields strings.Builder 71 78 for _, f := range mapToStructInput(input) {
M
json2go_test.go
··· 22 22 23 23 func TestTransformer_Transform(t *testing.T) { 24 24 tests := map[string]struct { 25 - input string 26 - output string 27 - err error 25 + input string 26 + output string 27 + structName string 28 + err error 28 29 }{ 29 30 "simple object": { 30 31 input: `{"name": "Olex", "active": true, "age": 420}`, ··· 37 38 "invalid json": { 38 39 err: ErrInvalidJSON, 39 40 input: `{"invalid":json}`, 41 + }, 42 + "invalid struct name, starts with number": { 43 + err: ErrInvalidStructName, 44 + structName: "1Name", 45 + }, 46 + "invalid struct name, has space": { 47 + err: ErrInvalidStructName, 48 + structName: "Name Name2", 49 + }, 50 + "invalid struct name, has non letter/number": { 51 + err: ErrInvalidStructName, 52 + structName: "Name$", 40 53 }, 41 54 "snake_case to CamelCase": { 42 55 input: `{"first_name": "Bob", "last_name": "Bobberson"}`, ··· 93 106 trans := NewTransformer() 94 107 for tname, tt := range tests { 95 108 t.Run(tname, func(t *testing.T) { 96 - result, err := trans.Transform("Out", tt.input) 109 + sn := "Out" 110 + if tt.structName != "" { 111 + sn = tt.structName 112 + } 113 + 114 + result, err := trans.Transform(sn, tt.input) 97 115 assertEqualErr(t, tt.err, err) 98 116 assertEqual(t, tt.output, result) 99 117 }) ··· 102 120 103 121 func assertEqualErr(t *testing.T, expected, actual error) { 104 122 t.Helper() 105 - if (expected != nil || actual != nil) && errors.Is(expected, actual) { 106 - t.Errorf("expected: %v, got: %v\n", expected, actual) 123 + if expected == nil && actual == nil { 124 + return 125 + } 126 + 127 + if expected == nil || actual == nil { 128 + t.Errorf("expected: %v, got: %v", expected, actual) 129 + return 130 + } 131 + 132 + if !errors.Is(actual, expected) { 133 + t.Errorf("expected error: %v, got: %v", expected, actual) 107 134 } 108 135 } 109 136