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 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器