Skip to content

Instantly share code, notes, and snippets.

@RSheremeta
Last active June 23, 2022 13:47
Show Gist options
  • Save RSheremeta/74ec5b9d8ddee9bf1d3b1b34ba819799 to your computer and use it in GitHub Desktop.
Save RSheremeta/74ec5b9d8ddee9bf1d3b1b34ba819799 to your computer and use it in GitHub Desktop.
Encode Golang Struct to JSON based on locale
// Basic JSON encoder
// Encoding from Struct to JSON
// Supported types: string, bool, float64, int64
// Touch and play:
// https://go.dev/play/p/BJETEuu8k3K
// Author: https://github.com/RSheremeta
package main
import (
"bytes"
"fmt"
"reflect"
"strconv"
"strings"
)
type encodingLocale string
const (
en encodingLocale = "en"
ua encodingLocale = "ua"
pl encodingLocale = "pl"
)
type City struct {
Name string `en:"name" ua:"імʼя" pl:"nazwać"`
Population float64 `en:"population" ua:"населення" pl:"ludzie"`
Capital bool `en:"capital" ua:"столиця" pl:"stolica"`
Weather int64 `en:"weather" ua:"погода" pl:"pogoda"`
Mayor string `en:"mayor" ua:"мер" pl:"burmistrz"`
}
func main() {
NYC := City{
Name: "New York",
Population: 19_510_000,
Capital: false,
Weather: 18,
Mayor: "Eric Adams",
}
Kyiv := City{
Name: "Kyiv",
Population: 2_884_000,
Capital: true,
Weather: 24,
Mayor: "Vitaliy Klytchko",
}
Warsaw := City{
Name: "Warsaw",
Population: 1_765_000,
Capital: true,
Weather: 13,
Mayor: "Rafał Trzaskowski",
}
nycEncoded, err := JSONEncode(NYC, en)
if err != nil {
panic(err)
}
fmt.Println(string(nycEncoded))
fmt.Println()
kyivEncoded, err := JSONEncode(Kyiv, ua)
if err != nil {
panic(err)
}
fmt.Println(string(kyivEncoded))
fmt.Println()
warsawEncoded, err := JSONEncode(Warsaw, pl)
if err != nil {
panic(err)
}
fmt.Println(string(warsawEncoded))
}
func JSONEncode(v interface{}, locale encodingLocale) ([]byte, error) {
buf := bytes.Buffer{}
reflectObjValue := reflect.ValueOf(v)
reflectObjType := reflect.TypeOf(v)
if reflectObjValue.Kind() != reflect.Struct {
return buf.Bytes(),
fmt.Errorf("ERROR: The value of kind %v is not supported\n", reflectObjValue.Kind().String())
}
buf.WriteString("{")
var resultJson []string
for i := 0; i < reflectObjValue.NumField(); i++ {
structField := reflectObjValue.Field(i)
structFieldType := reflectObjType.Field(i)
tag := structFieldType.Tag.Get(string(locale))
switch structField.Kind() {
case reflect.String:
strVal := structField.Interface().(string)
// build the pair
resultJson = append(resultJson, `"`+tag+`":"`+strVal+`"`)
case reflect.Int64:
int64Val := structField.Interface().(int64)
resultJson = append(resultJson, `"`+tag+`":`+strconv.FormatInt(int64Val, 10))
case reflect.Bool:
boolVal := structField.Interface().(bool)
resultJson = append(resultJson, `"`+tag+`":`+strconv.FormatBool(boolVal))
case reflect.Float64:
float64Val := structField.Interface().(float64)
resultJson = append(resultJson, `"`+tag+`":`+fmt.Sprintf("%f", float64Val))
default:
return buf.Bytes(),
fmt.Errorf("ERROR: Struct field with name %v and kind %v is not supported\n",
structFieldType.Name, structField.Kind(),
)
}
}
buf.WriteString(strings.Join(resultJson, ","))
buf.WriteString("}")
return buf.Bytes(), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment