代码之家  ›  专栏  ›  技术社区  ›  Anirudh Garg

接口转换:接口{}是映射[string]接口{},不是

  •  0
  • Anirudh Garg  · 技术社区  · 2 年前

    我定义了一些结构,如

    type EventPayload struct {
        IsAdded        bool   `json:"is_added"`
        IsUpdated      bool   `json:"is_updated"`
        IsDeleted      bool   `json:"is_deleted"`
    }
    
    type HubEvent struct {
        Time      string      `json:"time"`
        Payload   interface{} `json:"payload"`
    }
    
    type EventRecord struct {
        InputEventPayload HubEvent `json:"inputEventPayload"`
        EventID           string         `json:"eventId"`
    }
    

    现在,我有一个数组 EventRecord 我需要对其进行迭代。我需要做两件事:

    1. 对于数组中的每个eventRecord,我需要检查 InputEventPayload 是否存在
    2. 如果是,我需要转换 InputEventPayload.Payload 接口到 EventPayload 结构

    我已经创建了一个测试文件来测试我的代码 EventRecords 大堆

    []EventRecord{
        {
            EventID: "eventID-1",
        },
        {
            EventID: "eventID-2",
            InputEventPayload: HubEvent{
            Payload: EventPayload{
                IsAdded: true,
                IsUpdated: false,
            },
                },
        },
    }
    

    我的代码如下

    for _, record := range EventRecords {
    
        // check if the InputEventPayload exists in the record
        if record.InputEventPayload != (HubEvent{}) {
    
            // typecast
            payload := record.InputEventPayload.Payload.(EventPayload)
    
            // do something with the payload
        }
    }
    

    我不知道这是否是检查字段是否正确的方法 InputEventPayload 是否存在。 其次,当代码试图进行类型转换时,它会给我以下错误

    interface conversion: interface {} is map[string]interface {}, not EventPayload

    这里重要的是我不能改变这里任何结构的模式

    2 回复  |  直到 2 年前
        1
  •  0
  •   eik    2 年前

    问题(也是测试数据的问题)在于,您将JSON反序列化为 interface{} ,制作对象 map[string]interface{} 默认情况下。

    一种解决方案可能是再次对其进行序列化和反序列化:

        for _, record := range EventRecords {
            // check if the InputEventPayload exists in the record
            if record.InputEventPayload.Payload != nil {
                tmp, err := json.Marshal(record.InputEventPayload.Payload)
                if err != nil {
                    panic(err) // handle the error properly in your code
                }
                var event EventPayload
                if err := json.Unmarshal(tmp, &event); err != nil {
                    panic(err) // handle the error properly in your code
                }
                fmt.Println(event)
            }
        }
    

    最好直接使用正确的结构,你提到你不能这样做:

    type HubEvent struct {
        Time    string        `json:"time"`
        Payload *EventPayload `json:"payload"`
    }
    

    为了提出更好的解决方案,我们可能需要更多地了解您的问题,以及为什么结构是这样的,并且是不可变的。

        2
  •  0
  •   LeGEC    2 年前

    您可以将json取消序列化为任何内容。

    如果你需要针对的实际结构和你在问题中粘贴的结构一样简单,你可以复制粘贴该结构:

    type MyHubEvent struct{
        Time      string                    `json:"time"`
        Payload   *packagename.EventPayload `json:"payload"`
    }
    
    type MyEventRecord struct {
        InputEventPayload *MyHubEvent `json:"inputEventPayload"`
        EventID           string         `json:"eventId"`
    }
    
    
    func read(input io.Reader) ([]EventRecord, error) {
         var buffer []MyEventRecord
         err := json.NewDecoder(input).Decode(&buffer)
         if err != nil {
              return nil, err
         }
    
         // convert your inner structure to the expected structure:
         var result = make([]EventRecord, 0, len(buffer))
         for _, in := range buffer {
             out := EventRecord{
                EventID: in.EventID
             }
    
             payload := in.InputEventPayload
             if payload != nil && payload.Payload != nil {
                 out.InputEventPayload.Payload = *payload.Payload
             }
             result = append(result, out)
         }
         return result, nil
    }