all repos

json2go @ 998d829

convert json to go type annotations
3 files changed, 40 insertions(+), 30 deletions(-)
feat: indentation
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2025-11-27 14:55:49 +0200
Authored at: 2025-11-26 23:48:53 +0200
Change ID: wrrouvntmlqttnxlkxyymwryyxmqwywv
Parent: 917fe25
M json2go.go
···
        16
        16
         )

      
        17
        17
         

      
        18
        18
         type Transformer struct {

      
        19
        
        -	structName string

      
        
        19
        +	structName    string

      
        
        20
        +	currentIndent int

      
        20
        21
         }

      
        21
        22
         

      
        22
        23
         func NewTransformer() *Transformer {

      ···
        32
        33
         	}

      
        33
        34
         

      
        34
        35
         	t.structName = structName

      
        
        36
        +	t.currentIndent = 0

      
        35
        37
         

      
        36
        38
         	var input any

      
        37
        39
         	if err := json.Unmarshal([]byte(jsonStr), &input); err != nil {

      ···
        82
        84
         			f.field = "NotNamedField"

      
        83
        85
         		}

      
        84
        86
         

      
        
        87
        +		// increase indentation in case of building new struct

      
        
        88
        +		t.currentIndent++

      
        85
        89
         		fieldType := t.getGoType(fieldName, f.type_)

      
        
        90
        +		t.currentIndent--

      
        86
        91
         

      
        87
        92
         		// todo: toggle json tags generation

      
        88
        93
         		jsonTag := fmt.Sprintf("`json:\"%s\"`", f.field)

      
        89
        94
         

      
        90
        
        -		// todo: figure out the indentation, since it might have nested struct

      
        
        95
        +		indent := strings.Repeat("\t", t.currentIndent+1)

      
        91
        96
         		fields.WriteString(fmt.Sprintf(

      
        92
        
        -			"%s %s %s\n",

      
        
        97
        +			"%s%s %s %s\n",

      
        
        98
        +			indent,

      
        93
        99
         			fieldName,

      
        94
        100
         			fieldType,

      
        95
        101
         			jsonTag,

      
        96
        102
         		))

      
        97
        103
         	}

      
        98
        104
         

      
        99
        
        -	return fmt.Sprintf("struct {\n%s}", fields.String())

      
        
        105
        +	return fmt.Sprintf("struct {\n%s%s}",

      
        
        106
        +		fields.String(),

      
        
        107
        +		strings.Repeat("\t", t.currentIndent))

      
        100
        108
         }

      
        101
        109
         

      
        102
        110
         func (t *Transformer) getGoType(fieldName string, value any) string {

      
M json2go_internal_test.go
···
        14
        14
         				"age":      float64(20),

      
        15
        15
         			},

      
        16
        16
         			output: "struct {" +

      
        17
        
        -				field("Age", "int") +

      
        18
        
        -				field("Username", "string") + "\n}",

      
        
        17
        +				field(1, "Age", "int") +

      
        
        18
        +				field(1, "Username", "string") +

      
        
        19
        +				"\n}",

      
        19
        20
         		},

      
        20
        21
         		"empty slice": {

      
        21
        22
         			value:  make([]any, 0),

      ···
        82
        83
         				"active": true,

      
        83
        84
         			},

      
        84
        85
         			output: "struct {" +

      
        85
        
        -				field("Active", "bool", "active") +

      
        
        86
        +				field(1, "Active", "bool", "active") +

      
        86
        87
         				"\n}",

      
        87
        88
         		},

      
        88
        89
         		"with no named field": {

      
        89
        90
         			input: map[string]any{"": "user"},

      
        90
        91
         			output: "struct {" +

      
        91
        
        -				field("NotNamedField", "string", "NotNamedField") +

      
        
        92
        +				field(1, "NotNamedField", "string", "NotNamedField") +

      
        92
        93
         				"\n}",

      
        93
        94
         		},

      
        94
        95
         	}

      ···
        113
        114
         		"struct": {

      
        114
        115
         			input: map[string]any{"field": false},

      
        115
        116
         			output: c + "struct {" +

      
        116
        
        -				field("Field", "bool") + "\n}",

      
        
        117
        +				field(1, "Field", "bool") + "\n}",

      
        117
        118
         		},

      
        118
        119
         		"slice": {

      
        119
        120
         			input:  []any{"asdf", "jkl;"},

      
M json2go_test.go
···
        8
        8
         	"testing"

      
        9
        9
         )

      
        10
        10
         

      
        11
        
        -func field(name, type_ string, json_ ...string) string {

      
        
        11
        +func field(indentLvl int, name, type_ string, json_ ...string) string {

      
        
        12
        +	indent := strings.Repeat("\t", indentLvl)

      
        12
        13
         	if strings.Contains(type_, "struct") {

      
        13
        
        -		return fmt.Sprintf("\n%s %s", name, type_)

      
        
        14
        +		return fmt.Sprintf("\n%s%s %s", indent, name, type_)

      
        14
        15
         	}

      
        15
        16
         

      
        16
        17
         	tag := strings.ToLower(name)

      
        17
        18
         	if len(json_) == 1 {

      
        18
        19
         		tag = json_[0]

      
        19
        20
         	}

      
        20
        
        -	return fmt.Sprintf("\n%s %s `json:\"%s\"`", name, type_, tag)

      
        
        21
        +	return fmt.Sprintf("\n%s%s %s `json:\"%s\"`", indent, name, type_, tag)

      
        21
        22
         }

      
        22
        23
         

      
        23
        24
         func TestTransformer_Transform(t *testing.T) {

      ···
        30
        31
         		"simple object": {

      
        31
        32
         			input: `{"name": "Olex", "active": true, "age": 420}`,

      
        32
        33
         			output: "type Out struct {" +

      
        33
        
        -				field("Active", "bool") +

      
        34
        
        -				field("Age", "int") +

      
        35
        
        -				field("Name", "string") +

      
        
        34
        +				field(1, "Active", "bool") +

      
        
        35
        +				field(1, "Age", "int") +

      
        
        36
        +				field(1, "Name", "string") +

      
        36
        37
         				"\n}",

      
        37
        38
         		},

      
        38
        39
         		"invalid json": {

      ···
        54
        55
         		"snake_case to CamelCase": {

      
        55
        56
         			input: `{"first_name": "Bob", "last_name": "Bobberson"}`,

      
        56
        57
         			output: "type Out struct {" +

      
        57
        
        -				field("FirstName", "string", "first_name") +

      
        58
        
        -				field("LastName", "string", "last_name") +

      
        
        58
        +				field(1, "FirstName", "string", "first_name") +

      
        
        59
        +				field(1, "LastName", "string", "last_name") +

      
        59
        60
         				"\n}",

      
        60
        61
         		},

      
        61
        62
         		"nested object and array": {

      
        62
        63
         			input: `{"user": {"name": "Alice", "score": 95.5}, "tags": ["go", "json"]}`,

      
        63
        64
         			output: "type Out struct {" +

      
        64
        
        -				field("Tags", "[]string") +

      
        65
        
        -				field("User", "struct {") +

      
        66
        
        -				field("Name", "string") +

      
        67
        
        -				field("Score", "float64") +

      
        68
        
        -				"\n} `json:\"user\"`" +

      
        
        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\"`" +

      
        69
        70
         				"\n}",

      
        70
        71
         		},

      
        71
        72
         		"empty nested object": {

      
        72
        73
         			input: `{"user": {}}`,

      
        73
        74
         			output: "type Out struct {" +

      
        74
        
        -				field("User", "struct {") +

      
        75
        
        -				"\n} `json:\"user\"`" +

      
        
        75
        +				field(1, "User", "struct {") +

      
        
        76
        +				"\n\t} `json:\"user\"`" +

      
        76
        77
         				"\n}",

      
        77
        78
         		},

      
        78
        79
         		"array of object": {

      
        79
        80
         			input: `[{"name": "John"}, {"name": "Jane"}]`,

      
        80
        81
         			output: "type Out []struct {" +

      
        81
        
        -				field("Name", "string") +

      
        
        82
        +				field(1, "Name", "string") +

      
        82
        83
         				"\n}",

      
        83
        84
         		},

      
        84
        85
         		"empty array": {

      
        85
        86
         			input: `{"items": []}`,

      
        86
        87
         			output: "type Out struct {" +

      
        87
        
        -				field("Items", "[]any") +

      
        
        88
        +				field(1, "Items", "[]any") +

      
        88
        89
         				"\n}",

      
        89
        90
         		},

      
        90
        91
         		"null": {

      
        91
        92
         			input: `{"item": null}`,

      
        92
        93
         			output: `type Out struct {` +

      
        93
        
        -				field("Item", "any") +

      
        
        94
        +				field(1, "Item", "any") +

      
        94
        95
         				"\n}",

      
        95
        96
         		},

      
        96
        97
         		"numbers": {

      
        97
        98
         			input: `{"pos": 123, "neg": -321, "float": 420.69}`,

      
        98
        99
         			output: "type Out struct {" +

      
        99
        
        -				field("Float", "float64") +

      
        100
        
        -				field("Neg", "int") +

      
        101
        
        -				field("Pos", "int") +

      
        
        100
        +				field(1, "Float", "float64") +

      
        
        101
        +				field(1, "Neg", "int") +

      
        
        102
        +				field(1, "Pos", "int") +

      
        102
        103
         				"\n}",

      
        103
        104
         		},

      
        104
        105
         	}