dsa5211314 2017-04-10 14:00
浏览 442
已采纳

Golang将接口{}转换为struct

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条回答 默认 最新

  • duanji8887 2017-04-10 14:08
    关注

    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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算