[mirror] convert json to go types olexsmir.xyz/json2go

feat: indentation

olexsmir.xyz 998d8299 917fe252

verified
+12 -4
json2go.go
··· 16 ) 17 18 type Transformer struct { 19 - structName string 20 } 21 22 func NewTransformer() *Transformer { ··· 32 } 33 34 t.structName = structName 35 36 var input any 37 if err := json.Unmarshal([]byte(jsonStr), &input); err != nil { ··· 82 f.field = "NotNamedField" 83 } 84 85 fieldType := t.getGoType(fieldName, f.type_) 86 87 // todo: toggle json tags generation 88 jsonTag := fmt.Sprintf("`json:\"%s\"`", f.field) 89 90 - // todo: figure out the indentation, since it might have nested struct 91 fields.WriteString(fmt.Sprintf( 92 - "%s %s %s\n", 93 fieldName, 94 fieldType, 95 jsonTag, 96 )) 97 } 98 99 - return fmt.Sprintf("struct {\n%s}", fields.String()) 100 } 101 102 func (t *Transformer) getGoType(fieldName string, value any) string {
··· 16 ) 17 18 type Transformer struct { 19 + structName string 20 + currentIndent int 21 } 22 23 func NewTransformer() *Transformer { ··· 33 } 34 35 t.structName = structName 36 + t.currentIndent = 0 37 38 var input any 39 if err := json.Unmarshal([]byte(jsonStr), &input); err != nil { ··· 84 f.field = "NotNamedField" 85 } 86 87 + // increase indentation in case of building new struct 88 + t.currentIndent++ 89 fieldType := t.getGoType(fieldName, f.type_) 90 + t.currentIndent-- 91 92 // todo: toggle json tags generation 93 jsonTag := fmt.Sprintf("`json:\"%s\"`", f.field) 94 95 + indent := strings.Repeat("\t", t.currentIndent+1) 96 fields.WriteString(fmt.Sprintf( 97 + "%s%s %s %s\n", 98 + indent, 99 fieldName, 100 fieldType, 101 jsonTag, 102 )) 103 } 104 105 + return fmt.Sprintf("struct {\n%s%s}", 106 + fields.String(), 107 + strings.Repeat("\t", t.currentIndent)) 108 } 109 110 func (t *Transformer) getGoType(fieldName string, value any) string {
+6 -5
json2go_internal_test.go
··· 14 "age": float64(20), 15 }, 16 output: "struct {" + 17 - field("Age", "int") + 18 - field("Username", "string") + "\n}", 19 }, 20 "empty slice": { 21 value: make([]any, 0), ··· 82 "active": true, 83 }, 84 output: "struct {" + 85 - field("Active", "bool", "active") + 86 "\n}", 87 }, 88 "with no named field": { 89 input: map[string]any{"": "user"}, 90 output: "struct {" + 91 - field("NotNamedField", "string", "NotNamedField") + 92 "\n}", 93 }, 94 } ··· 113 "struct": { 114 input: map[string]any{"field": false}, 115 output: c + "struct {" + 116 - field("Field", "bool") + "\n}", 117 }, 118 "slice": { 119 input: []any{"asdf", "jkl;"},
··· 14 "age": float64(20), 15 }, 16 output: "struct {" + 17 + field(1, "Age", "int") + 18 + field(1, "Username", "string") + 19 + "\n}", 20 }, 21 "empty slice": { 22 value: make([]any, 0), ··· 83 "active": true, 84 }, 85 output: "struct {" + 86 + field(1, "Active", "bool", "active") + 87 "\n}", 88 }, 89 "with no named field": { 90 input: map[string]any{"": "user"}, 91 output: "struct {" + 92 + field(1, "NotNamedField", "string", "NotNamedField") + 93 "\n}", 94 }, 95 } ··· 114 "struct": { 115 input: map[string]any{"field": false}, 116 output: c + "struct {" + 117 + field(1, "Field", "bool") + "\n}", 118 }, 119 "slice": { 120 input: []any{"asdf", "jkl;"},
+22 -21
json2go_test.go
··· 8 "testing" 9 ) 10 11 - func field(name, type_ string, json_ ...string) string { 12 if strings.Contains(type_, "struct") { 13 - return fmt.Sprintf("\n%s %s", name, type_) 14 } 15 16 tag := strings.ToLower(name) 17 if len(json_) == 1 { 18 tag = json_[0] 19 } 20 - return fmt.Sprintf("\n%s %s `json:\"%s\"`", name, type_, tag) 21 } 22 23 func TestTransformer_Transform(t *testing.T) { ··· 30 "simple object": { 31 input: `{"name": "Olex", "active": true, "age": 420}`, 32 output: "type Out struct {" + 33 - field("Active", "bool") + 34 - field("Age", "int") + 35 - field("Name", "string") + 36 "\n}", 37 }, 38 "invalid json": { ··· 54 "snake_case to CamelCase": { 55 input: `{"first_name": "Bob", "last_name": "Bobberson"}`, 56 output: "type Out struct {" + 57 - field("FirstName", "string", "first_name") + 58 - field("LastName", "string", "last_name") + 59 "\n}", 60 }, 61 "nested object and array": { 62 input: `{"user": {"name": "Alice", "score": 95.5}, "tags": ["go", "json"]}`, 63 output: "type Out struct {" + 64 - field("Tags", "[]string") + 65 - field("User", "struct {") + 66 - field("Name", "string") + 67 - field("Score", "float64") + 68 - "\n} `json:\"user\"`" + 69 "\n}", 70 }, 71 "empty nested object": { 72 input: `{"user": {}}`, 73 output: "type Out struct {" + 74 - field("User", "struct {") + 75 - "\n} `json:\"user\"`" + 76 "\n}", 77 }, 78 "array of object": { 79 input: `[{"name": "John"}, {"name": "Jane"}]`, 80 output: "type Out []struct {" + 81 - field("Name", "string") + 82 "\n}", 83 }, 84 "empty array": { 85 input: `{"items": []}`, 86 output: "type Out struct {" + 87 - field("Items", "[]any") + 88 "\n}", 89 }, 90 "null": { 91 input: `{"item": null}`, 92 output: `type Out struct {` + 93 - field("Item", "any") + 94 "\n}", 95 }, 96 "numbers": { 97 input: `{"pos": 123, "neg": -321, "float": 420.69}`, 98 output: "type Out struct {" + 99 - field("Float", "float64") + 100 - field("Neg", "int") + 101 - field("Pos", "int") + 102 "\n}", 103 }, 104 }
··· 8 "testing" 9 ) 10 11 + func field(indentLvl int, name, type_ string, json_ ...string) string { 12 + indent := strings.Repeat("\t", indentLvl) 13 if strings.Contains(type_, "struct") { 14 + return fmt.Sprintf("\n%s%s %s", indent, name, type_) 15 } 16 17 tag := strings.ToLower(name) 18 if len(json_) == 1 { 19 tag = json_[0] 20 } 21 + return fmt.Sprintf("\n%s%s %s `json:\"%s\"`", indent, name, type_, tag) 22 } 23 24 func TestTransformer_Transform(t *testing.T) { ··· 31 "simple object": { 32 input: `{"name": "Olex", "active": true, "age": 420}`, 33 output: "type Out struct {" + 34 + field(1, "Active", "bool") + 35 + field(1, "Age", "int") + 36 + field(1, "Name", "string") + 37 "\n}", 38 }, 39 "invalid json": { ··· 55 "snake_case to CamelCase": { 56 input: `{"first_name": "Bob", "last_name": "Bobberson"}`, 57 output: "type Out struct {" + 58 + field(1, "FirstName", "string", "first_name") + 59 + field(1, "LastName", "string", "last_name") + 60 "\n}", 61 }, 62 "nested object and array": { 63 input: `{"user": {"name": "Alice", "score": 95.5}, "tags": ["go", "json"]}`, 64 output: "type Out struct {" + 65 + field(1, "Tags", "[]string") + 66 + field(1, "User", "struct {") + 67 + field(2, "Name", "string") + 68 + field(2, "Score", "float64") + 69 + "\n\t} `json:\"user\"`" + 70 "\n}", 71 }, 72 "empty nested object": { 73 input: `{"user": {}}`, 74 output: "type Out struct {" + 75 + field(1, "User", "struct {") + 76 + "\n\t} `json:\"user\"`" + 77 "\n}", 78 }, 79 "array of object": { 80 input: `[{"name": "John"}, {"name": "Jane"}]`, 81 output: "type Out []struct {" + 82 + field(1, "Name", "string") + 83 "\n}", 84 }, 85 "empty array": { 86 input: `{"items": []}`, 87 output: "type Out struct {" + 88 + field(1, "Items", "[]any") + 89 "\n}", 90 }, 91 "null": { 92 input: `{"item": null}`, 93 output: `type Out struct {` + 94 + field(1, "Item", "any") + 95 "\n}", 96 }, 97 "numbers": { 98 input: `{"pos": 123, "neg": -321, "float": 420.69}`, 99 output: "type Out struct {" + 100 + field(1, "Float", "float64") + 101 + field(1, "Neg", "int") + 102 + field(1, "Pos", "int") + 103 "\n}", 104 }, 105 }