@exitialis

Как в Go преобразовать struct в map[string]string?

Добрый день, я новичек в golang и совсем недавно начал изучать его. Появилась такая задача - необходимо пройти все свойства в структуре и преобразовать их в map[string][string]. При этом, в структуре есть вложенная структура, и нужно сделать так, чтобы поля из вложенной структуры из свойства Key стали ключами в map, а из свойства Text стали значениями. Изначально использовал json.Marshal и json.Unmarshal, но при этом терялась вложенная структура. Попытался воспользоваться библиотекой github.com/fatih/structs, но с ее помощью застрял на одном моменте - Go ругается, что в типе interface{} нет свойств Text или Key, как быть? Пример кода:

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: "test@mail.ru",
		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
		}
	}
  • Вопрос задан
  • 4150 просмотров
Решения вопроса 1
@exitialis Автор вопроса
Решил задачу при помощи Type assertions
req := CreateInvoiceRequest{}
	req.Payload.Amount = "1"
	req.Payload.EndDate = "2019-06-26 10:00:00"
	email := ExtField{
		Text: "test@mail.ru",
		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
		}
	}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Если вам такое понадобилось, скорее всего вы делаете что-то не так.
Если очень надо, для таких целей есть пакет reflect в стандартной бибилотеке.

Ваш код не компилится, потому что вам надо привести interface{} в нужному типу. Например так:
for _, field := range fields {
	if field.Name() == "fields" {
		if field, ok := field.Value().(ExtField); ok {
			res[field.Key] = field.Text
		}
	}
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы