all repos

json2go @ 25c3e78

convert json to go type annotations
2 files changed, 196 insertions(+), 2 deletions(-)
i might have over done it
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2025-11-26 22:31:34 +0200
Authored at: 2025-11-26 19:58:43 +0200
Change ID: uvvyyyrzwvvposyqosnyxnoqlsxkmspz
Parent: 1609c23
M json2go.go
···
        49
        49
         

      
        50
        50
         	case []any:

      
        51
        51
         		if len(v) == 0 {

      
        52
        
        -			return fmt.Sprintf("type %s []any", t.structName)

      
        
        52
        +			return fmt.Sprintf("type %s []any", typeName)

      
        53
        53
         		}

      
        54
        54
         

      
        55
        55
         		type_ := t.getGoType(typeName+"Item", v[0])

      ···
        78
        78
         	for _, f := range mapToStructInput(input) {

      
        79
        79
         		fieldName := t.toGoFieldName(f.field)

      
        80
        80
         		if fieldName == "" {

      
        81
        
        -			fieldName = "Field"

      
        
        81
        +			fieldName = "NotNamedField"

      
        
        82
        +			f.field = "NotNamedField"

      
        82
        83
         		}

      
        83
        84
         

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

      
A json2go_internal_test.go
···
        
        1
        +package json2go

      
        
        2
        +

      
        
        3
        +import "testing"

      
        
        4
        +

      
        
        5
        +func TestTransformer_GetGoType(t *testing.T) {

      
        
        6
        +	tests := map[string]struct {

      
        
        7
        +		value     any

      
        
        8
        +		fieldName string

      
        
        9
        +		output    string

      
        
        10
        +	}{

      
        
        11
        +		"struct": {

      
        
        12
        +			value: map[string]any{

      
        
        13
        +				"username": "user-ovich",

      
        
        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),

      
        
        22
        +			output: "[]any",

      
        
        23
        +		},

      
        
        24
        +		"slice of ints": {

      
        
        25
        +			value:  []any{float64(3), float64(123)},

      
        
        26
        +			output: "[]int",

      
        
        27
        +		},

      
        
        28
        +		"slice of floats": {

      
        
        29
        +			value:  []any{float64(3.4), float64(123.3)},

      
        
        30
        +			output: "[]float64",

      
        
        31
        +		},

      
        
        32
        +		"slice of strings": {

      
        
        33
        +			value:  []any{"asdf", "jalkjsd"},

      
        
        34
        +			output: "[]string",

      
        
        35
        +		},

      
        
        36
        +		"slice of bool": {

      
        
        37
        +			value:  []any{false, true, false},

      
        
        38
        +			output: "[]bool",

      
        
        39
        +		},

      
        
        40
        +		"int": {

      
        
        41
        +			value:  float64(1233),

      
        
        42
        +			output: "int",

      
        
        43
        +		},

      
        
        44
        +		"float64": {

      
        
        45
        +			value:  float64(1233.23),

      
        
        46
        +			output: "float64",

      
        
        47
        +		},

      
        
        48
        +		"bool": {

      
        
        49
        +			value:  false,

      
        
        50
        +			output: "bool",

      
        
        51
        +		},

      
        
        52
        +		"any": {

      
        
        53
        +			value:  nil,

      
        
        54
        +			output: "any",

      
        
        55
        +		},

      
        
        56
        +	}

      
        
        57
        +

      
        
        58
        +	trans := NewTransformer()

      
        
        59
        +	for tname, tt := range tests {

      
        
        60
        +		t.Run(tname, func(t *testing.T) {

      
        
        61
        +			t.Parallel()

      
        
        62
        +

      
        
        63
        +			fieldName := "field"

      
        
        64
        +			if tt.fieldName != "" {

      
        
        65
        +				fieldName = tt.fieldName

      
        
        66
        +			}

      
        
        67
        +

      
        
        68
        +			res := trans.getGoType(fieldName, tt.value)

      
        
        69
        +			assertEqual(t, tt.output, res)

      
        
        70
        +		})

      
        
        71
        +	}

      
        
        72
        +}

      
        
        73
        +

      
        
        74
        +func TestTransformer_buildStruct(t *testing.T) {

      
        
        75
        +	tests := map[string]struct {

      
        
        76
        +		input  map[string]any

      
        
        77
        +		output string

      
        
        78
        +	}{

      
        
        79
        +		"simple struct": {

      
        
        80
        +			input: map[string]any{

      
        
        81
        +				// only one value, because of the inconsistent ordering of maps

      
        
        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
        +	}

      
        
        95
        +

      
        
        96
        +	trans := NewTransformer()

      
        
        97
        +	for tname, tt := range tests {

      
        
        98
        +		t.Run(tname, func(t *testing.T) {

      
        
        99
        +			t.Parallel()

      
        
        100
        +

      
        
        101
        +			res := trans.buildStruct(tt.input)

      
        
        102
        +			assertEqual(t, tt.output, res)

      
        
        103
        +		})

      
        
        104
        +	}

      
        
        105
        +}

      
        
        106
        +

      
        
        107
        +func TestTransformer_getTypeAnnotation(t *testing.T) {

      
        
        108
        +	c := "type Typeich "

      
        
        109
        +	tests := map[string]struct {

      
        
        110
        +		input  any

      
        
        111
        +		output string

      
        
        112
        +	}{

      
        
        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;"},

      
        
        120
        +			output: c + "[]string",

      
        
        121
        +		},

      
        
        122
        +		"empty slice": {

      
        
        123
        +			input:  make([]any, 0),

      
        
        124
        +			output: c + "[]any",

      
        
        125
        +		},

      
        
        126
        +		"string": {

      
        
        127
        +			input:  "asdf",

      
        
        128
        +			output: c + "string",

      
        
        129
        +		},

      
        
        130
        +		"int": {

      
        
        131
        +			input:  float64(123),

      
        
        132
        +			output: c + "int",

      
        
        133
        +		},

      
        
        134
        +		"float64": {

      
        
        135
        +			input:  float64(123.69),

      
        
        136
        +			output: c + "float64",

      
        
        137
        +		},

      
        
        138
        +		"bool": {

      
        
        139
        +			input:  true,

      
        
        140
        +			output: c + "bool",

      
        
        141
        +		},

      
        
        142
        +		"any": {

      
        
        143
        +			input:  nil,

      
        
        144
        +			output: c + "any",

      
        
        145
        +		},

      
        
        146
        +	}

      
        
        147
        +

      
        
        148
        +	trans := NewTransformer()

      
        
        149
        +	for tname, tt := range tests {

      
        
        150
        +		t.Run(tname, func(t *testing.T) {

      
        
        151
        +			t.Parallel()

      
        
        152
        +

      
        
        153
        +			res := trans.getTypeAnnotation("Typeich", tt.input)

      
        
        154
        +			assertEqual(t, tt.output, res)

      
        
        155
        +		})

      
        
        156
        +	}

      
        
        157
        +}

      
        
        158
        +

      
        
        159
        +func TestTransformer_toGoFieldName(t *testing.T) {

      
        
        160
        +	tests := map[string]string{

      
        
        161
        +		"input":         "Input",

      
        
        162
        +		"Input":         "Input",

      
        
        163
        +		"long_name":     "LongName",

      
        
        164
        +		"a_lot_of_____": "ALotOf",

      
        
        165
        +		"__name":        "Name",

      
        
        166
        +	}

      
        
        167
        +

      
        
        168
        +	trans := NewTransformer()

      
        
        169
        +	for input, output := range tests {

      
        
        170
        +		t.Run(input, func(t *testing.T) {

      
        
        171
        +			t.Parallel()

      
        
        172
        +

      
        
        173
        +			res := trans.toGoFieldName(input)

      
        
        174
        +			assertEqual(t, output, res)

      
        
        175
        +		})

      
        
        176
        +	}

      
        
        177
        +}

      
        
        178
        +

      
        
        179
        +func TestMapToStructInput(t *testing.T) {

      
        
        180
        +	inp := map[string]any{

      
        
        181
        +		"field1": nil,

      
        
        182
        +		"field2": true,

      
        
        183
        +		"a":      123,

      
        
        184
        +		"user":   map[string]any{},

      
        
        185
        +	}

      
        
        186
        +

      
        
        187
        +	assertEqual(t, mapToStructInput(inp), []structInput{

      
        
        188
        +		{"a", 123},

      
        
        189
        +		{"field1", nil},

      
        
        190
        +		{"field2", true},

      
        
        191
        +		{"user", map[string]any{}},

      
        
        192
        +	})

      
        
        193
        +}