Challenge 1 - Reflection
- Go course
- Advanced
- Lesson 65/68
- 8 min
Write a tool that produces JSON from a struct with reflect.
Challenge: a mini JSON encoder
In this challenge you will write a small encoder that reads struct fields by their tags using reflection. Rules: the field name comes from the json tag; if the tag is "-" the field is skipped; without a tag the field name is used.
type User struct {
Ad string `json:"ad"`
Sifre string `json:"-"`
Yas int
}
// expected: ad=Ada Yas=36Plan
Steps: get reflect.TypeOf and reflect.ValueOf → NumField loop → read the tag for each field → continue on "-" → f.Name if empty → append a name=value piece to a slice → join with strings.Join. On unexported (lower-case) fields Interface() panics; skip them too with f.IsExported().
Practice Write the encoder
Write encode(v any) string and print the result for the User{"Ada", "1234", 36} value above. The output must be ad=Ada Yas=36.
Starter code
package main
import (
"fmt"
"reflect"
"strings"
)
func main() {
// buraya yaz
}Sample solution
package main
import (
"fmt"
"reflect"
"strings"
)
type User struct {
Ad string `json:"ad"`
Sifre string `json:"-"`
Yas int
}
func encode(v any) string {
t, val := reflect.TypeOf(v), reflect.ValueOf(v)
var parts []string
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
tag := f.Tag.Get("json")
if tag == "-" || !f.IsExported() {
continue
}
if tag == "" {
tag = f.Name
}
parts = append(parts, fmt.Sprintf("%s=%v", tag, val.Field(i).Interface()))
}
return strings.Join(parts, " ")
}
func main() {
fmt.Println(encode(User{"Ada", "1234", 36}))
}Expected output
ad=Ada Yas=36
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Where do you get the name of a field with no tag?
- Tag.Get("json")
- Value.String()
- Type.Name()
- StructField.Name Correct answer
Explanation: Tag.Get returns empty; in that case StructField.Name (the Go field name) is used. Type.Name() is the struct type's name.
2 Skip the field
if tag == "-" || !f.IsExported() {
____
}
if tag == "-" || !f.IsExported() {
continue
}
Explanation: continue skips just this field and moves to the next iteration.
3 Rule and code
| Term | Meaning |
|---|---|
Etiket "-" |
continue |
No tag |
f.Name |
Unexported field |
!f.IsExported() |
Joining |
strings.Join |