2017-04-10 164 views
1

我想在下面的代碼中改進getCustomerFromDTO方法,我需要從接口{}創建一個結構,並且當前我需要將該接口編組爲byte [],然後解組該數組到我的結構 - 必須有更好的方法。Golang convert interface {} to struct

我的用例是,我通過rabbitmq發送結構併發送它們,我使用這個通用的DTO包裝器,它具有關於它們的其他特定於域的數據。 當我收到來自rabbit mq的DTO時,消息下面的一層被解組到我的DTO,然後我需要從該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 
} 

回答

7

解編DTO之前,請將Data字段設置爲您所期望的類型。

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) 
} 

如果你沒有初始化的DTO的Data領域的能力,這是取消封送之前,你可以在拆封後使用類型斷言。包裝encoding/json unamrshals interface{}類型值轉換爲map[string]interface{},讓您的代碼會是這個樣子:

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 
} 
+0

的DTO拆封由包我用做它是所有接收到的消息是相同的。在我的應用程序中,我收到了一個已組裝的DTO – Tomas

+0

而您無法修改此軟件包?這是第三方嗎? – mkopriva

+0

我可以修改它,但由於它是一個通用包,在解組DTO時,我不知道它攜帶的結構類型是數據字段 – Tomas