英文:
Golang convert interface{} to struct
问题
我想改进下面代码中的getCustomerFromDTO方法,我需要从interface{}创建一个struct,目前我需要将该interface序列化为byte[],然后再将数组反序列化为我的struct - 必须有更好的方法。
我的使用案例是通过rabbitmq发送structs,并且为了发送它们,我使用了这个通用的DTO包装器,其中包含有关它们的附加领域特定数据。
当我从rabbit mq接收DTO时,消息的下一层将被反序列化为我的DTO,然后我需要从该DTO中获取我的struct。
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// more fields with important meta-data about the message...
}
func main() {
// create a customer, add it to DTO object and marshal it
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{Data: customer}
byteData, _ := json.Marshal(dtoToSend)
// unmarshal it (usually after receiving bytes from somewhere)
receivedDTO := UniversalDTO{}
json.Unmarshal(byteData, &receivedDTO)
//Attempt to unmarshall our customer
receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
customer := Customer{}
bodyBytes, _ := json.Marshal(data)
json.Unmarshal(bodyBytes, &customer)
return customer
}
英文:
I want to improve the getCustomerFromDTO method in the code below, I need to create a struct from an interface{} and currently i need to marshall that interface to byte[] and then unmarshal the array to my struct - there must be a better way.
My use case is that I send structs via rabbitmq and to send them I use this general DTO wrapper that has additional domain specific data about them.
When I receive the DTO from rabbit mq one layer below the message is unmarshaled to my DTO and then i need to get my struct from that DTO.
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// more fields with important meta-data about the message...
}
func main() {
// create a customer, add it to DTO object and marshal it
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{customer}
byteData, _ := json.Marshal(dtoToSend)
// unmarshal it (usually after receiving bytes from somewhere)
receivedDTO := UniversalDTO{}
json.Unmarshal(byteData, &receivedDTO)
//Attempt to unmarshall our customer
receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
customer := Customer{}
bodyBytes, _ := json.Marshal(data)
json.Unmarshal(bodyBytes, &customer)
return customer
}
答案1
得分: 31
在解组装 DTO 之前,将 Data
字段设置为你期望的类型。
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// 其他包含消息重要元数据的字段...
}
func main() {
// 创建一个 Customer,将其添加到 DTO 对象并进行编组
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{Data: customer}
byteData, _ := json.Marshal(dtoToSend)
// 解组装(通常在从某处接收字节后进行)
receivedCustomer := &Customer{}
receivedDTO := UniversalDTO{Data: receivedCustomer}
json.Unmarshal(byteData, &receivedDTO)
// 完成
fmt.Println(receivedCustomer)
}
如果在解组装 DTO 之前无法初始化 Data
字段,你可以在解组装后使用类型断言。encoding/json
包将 interface{}
类型的值解组装为 map[string]interface{}
,因此你的代码将如下所示:
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// 其他包含消息重要元数据的字段...
}
func main() {
// 创建一个 Customer,将其添加到 DTO 对象并进行编组
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{Data: customer}
byteData, _ := json.Marshal(dtoToSend)
// 解组装(通常在从某处接收字节后进行)
receivedDTO := UniversalDTO{}
json.Unmarshal(byteData, &receivedDTO)
// 尝试从 DTO 中解组装我们的 Customer
receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
m := data.(map[string]interface{})
customer := Customer{}
if name, ok := m["name"].(string); ok {
customer.Name = name
}
return customer
}
英文:
Before unmarshaling the DTO, set the Data
field to the type you expect.
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// more fields with important meta-data about the message...
}
func main() {
// create a customer, add it to DTO object and marshal it
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{customer}
byteData, _ := json.Marshal(dtoToSend)
// unmarshal it (usually after receiving bytes from somewhere)
receivedCustomer := &Customer{}
receivedDTO := UniversalDTO{Data: receivedCustomer}
json.Unmarshal(byteData, &receivedDTO)
//done
fmt.Println(receivedCustomer)
}
If you don't have the ability to initialize the Data
field on the DTO before it's unmarshaled, you can use type assertion after the unmarshaling. Package encoding/json
unamrshals interface{}
type values into a map[string]interface{}
, so your code would look something like this:
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// more fields with important meta-data about the message...
}
func main() {
// create a customer, add it to DTO object and marshal it
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{customer}
byteData, _ := json.Marshal(dtoToSend)
// unmarshal it (usually after receiving bytes from somewhere)
receivedDTO := UniversalDTO{}
json.Unmarshal(byteData, &receivedDTO)
//Attempt to unmarshall our customer
receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
m := data.(map[string]interface{})
customer := Customer{}
if name, ok := m["name"].(string); ok {
customer.Name = name
}
return customer
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论