Answer the question
In order to leave comments, you need to log in
How to convert struct to map[string]string in Go?
Hello, I'm new to golang and just recently started learning it. There was such a task - it is necessary to go through all the properties in the structure and convert them to map[string][string]. At the same time, the structure has a nested structure, and you need to make sure that the fields from the nested structure from the Key property become keys in the map, and from the Text property become values. I originally used json.Marshal and json.Unmarshal, but the nested structure was lost. I tried to use the github.com/fatih/structs library, but with its help I got stuck at one point - Go swears that there are no Text or Key properties in the interface{} type, what to do? Code example:
type Invoicing struct {
XMLName xml.Name
Text string
Sign string
}
type InvoiceRequest struct {
Invoicing
}
type ExtFields struct {
XMLName xml.Name
Fields []ExtField
}
type ExtField struct {
Text string
Key string
}
type CreateInvoiceRequest struct {
InvoiceRequest
Payload struct {
MerchantId string
ShopId string
ShopName string
OrderId string
Amount string
EndDate string
ShortDesc string
FullDesc string
ReturnURL string
ExtFields ExtFields
}
}
req := CreateInvoiceRequest{}
req.Payload.Amount = "1"
req.Payload.EndDate = "2019-06-26 10:00:00"
email := ExtField{
Text: "[email protected]",
Key: "email",
}
req.Payload.ExtFields.Fields = make([]ExtField, 0)
req.Payload.ExtFields.Fields = append(req.Payload.ExtFields.Fields, email)
res := make(map[string]string)
fields := structs.Fields(req.Payload)
for _, field := range fields {
value := field.Value()
if field.Name() == "fields" {
if t, ok := value.(string); ok {
res[field.Value().Key] = field.Value().Text
}
}
t, ok := value.(string);
if ok {
res[field.Name()] = t
}
}
Answer the question
In order to leave comments, you need to log in
Solved the problem using Type assertions
req := CreateInvoiceRequest{}
req.Payload.Amount = "1"
req.Payload.EndDate = "2019-06-26 10:00:00"
email := ExtField{
Text: "[email protected]",
Key: "email",
}
req.Payload.ExtFields.Fields = make([]ExtField, 0)
req.Payload.ExtFields.Fields = append(req.Payload.ExtFields.Fields, email)
res := make(map[string]string)
fields := structs.Fields(req.Payload)
for _, field := range fields {
value := field.Value()
if field.Name() == "ExtFields" {
if t, ok := field.Value().(ExtFields); ok && !field.IsZero() {
for _, extField := range t.Fields {
res[extField.Key] = extField.Text
}
continue
}
if t, ok := value.(*ExtField); ok {
res[t.Key] = t.Text
continue
}
}
t, ok := value.(string);
if ok {
res[field.Name()] = t
continue
}
}
If you need this, most likely you are doing something wrong. If you really need it, there is a reflect package in the standard library
for such purposes .
Your code won't compile because you have to cast interface{} to the correct type. For example like this:
for _, field := range fields {
if field.Name() == "fields" {
if field, ok := field.Value().(ExtField); ok {
res[field.Key] = field.Text
}
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question