I have a constutil package where I have defined some const values using iota.
package constutil
type UserType uint
const (
Free UserType = iota + 1
Premium UserType
...
)
From json
I will get {"user": "Premium", ...}
. Now I need to save the value of the user like for Premium
it's 2
. I tried to get the value like this:
constutil.(req.User)
But it didn't work as req.User
returns a string
like: "Premium"
.
I can just do it using map[string]uint
. But is there any way of doing it using iota
?
Its best to use const string for such Enum use case.
type UserType string
const(
Premium UserType = "Premium"
)
OR else define custom marshal/unmasrshal:
package main
import (
"fmt"
"encoding/json"
)
type UserType uint
func (u UserType) String() string{
return "Premium"
}
const(
Premium UserType = 1
)
type User struct{
T UserType `json:"type"`
}
func (u *User) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
T string
}{
T: fmt.Sprint(u.T),
})
}
func (u *User) UnmarshalJSON(data []byte) error {
aux := &struct {
T string `json:"type"`
}{ }
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
fmt.Println(aux.T)
switch aux.T{
case "Premium":
u.T = Premium
}
return nil
}
func main() {
b := []byte(`{"type":"Premium"}`)
x := new(User)
if err := json.Unmarshal(b, x); err != nil{
fmt.Printf("err: %v
", err)
}
fmt.Printf("unmasrshalled: %v
", *x)
fmt.Printf("type: %d
", x.T)
b, _ = json.Marshal(x)
fmt.Printf("marshalled: %v
", string(b))
}
Don't think there is any built-in way of mapping between iota
values and strings. There are some tools that generate code for doing the mapping.
I've been in similar situations and i've done something like this when I didn't want to depend on generators or other tools. Hope it serves as a start for something.
https://play.golang.org/p/MxPL-0FVGMt
package main
import (
"encoding/json"
"fmt"
)
type UserType uint
const (
UserTypeFree UserType = iota
UserTypePremium
)
var UserTypeToString = map[UserType]string{
UserTypeFree: "Free",
UserTypePremium: "Premium",
}
var UserTypeFromString = map[string]UserType{
"Free": UserTypeFree,
"Premium": UserTypePremium,
}
func (ut UserType) String() string {
if s, ok := UserTypeToString[ut]; ok {
return s
}
return "unknown"
}
func (ut UserType) MarshalJSON() ([]byte, error) {
if s, ok := UserTypeToString[ut]; ok {
return json.Marshal(s)
}
return nil, fmt.Errorf("unknown user type %d", ut)
}
func (ut *UserType) UnmarshalJSON(text []byte) error {
var s string
if err := json.Unmarshal(text, &s); err != nil {
return err
}
var v UserType
var ok bool
if v, ok = UserTypeFromString[s]; !ok {
return fmt.Errorf("unknown user type %s", s)
}
*ut = v
return nil
}
func main() {
var ut UserType
json.Unmarshal([]byte(`"Free"`), &ut)
fmt.Printf("%#v %v
", ut, ut)
b, _ := json.Marshal(ut)
fmt.Printf("%v
", string(b))
}