Last active
June 23, 2022 13:47
-
-
Save RSheremeta/74ec5b9d8ddee9bf1d3b1b34ba819799 to your computer and use it in GitHub Desktop.
Encode Golang Struct to JSON based on locale
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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