首页 > 解决方案 > 无法将 dynamodb 结果解组为具有定义为类型接口的字段的结构

问题描述

我有以下结构定义:

type Job struct {
    ID         string            `json:"id" dynamodbav:"id"`
    Ref        string            `json:"ref_id" dynamodbav:"ref_id"`
    Created    string            `json:"created_at,omitempty" dynamodbav:"created_at"`
    Stages     map[string]Status `json:"stages,omitempty" dynamodbav:"stages"`
}

// Status interface
type Status interface {
    GetMessage() string
}

// Failure struct
type Failure struct {
    Message string `json:"error_message,omitempty" dynamodbav:"message"`
}

// GetMessage returns the error message
func (f *Failure) GetMessage() string {
    return f.Message
}

// Success struct
type Success struct {
    Message string `json:"success_message,omitempty" dynamodbav:"message"`
}

// GetMessage returns the success message
func (s *Success) GetMessage() string {
    return s.Message
}

FailureSuccess结构满足 Status 接口的地方

我正在尝试将来自 dynamodb 的响应解组到 Job 结构中:

func getJobByID(id, table string) (*Job, error) {
    var (
        db = dynamodb.New(sess)

        key = map[string]*dynamodb.AttributeValue{
            "id": {
                S: aws.String(id),
            },
        }

        ip = &dynamodb.GetItemInput{
            TableName: aws.String(table),
            Key:       key,
        }
    )

    res, err := db.GetItem(ip)
    if err != nil {
        return nil, err
    }

    if res.Item == nil {
        return nil, errors.New("Not found")
    }

    var j *Job
    if err := dynamodbattribute.UnmarshalMap(res.Item, &j); err != nil {
        return nil, err
    }

    return j, nil
}

dynamodb 对象看起来像

{
  "created_at": {
    "S": "2020-07-21T06:40:53Z"
  },
  "id": {
    "S": "ca237361-7deb-4a28-872d-a602b9b1df67"
  },
  "stages": {
    "M": {
      "stage1": {
        "M": {
          "message": {
            "S": "Completed"
          }
        }
      },
      "stage2": {
        "M": {
          "message": {
            "S": "Completed"
          }
        }
      },
      "stage3": {
        "M": {
          "message": {
            "S": "Completed"
          }
        }
      }
    }
  },
  "ref_id": {
    "S": "test-reference"
  }
}

我得到的错误是: panic: reflect.Set: value of type map[string]interface {} is not assignable to type main.Status

我认为问题在于,我试图将一个类型解组string为一个interface,它无法获得导致恐慌的接口的具体类型。

我的问题是如何以惯用的方式解决此问题。

谢谢你们。

标签: amazon-web-servicesgoamazon-dynamodbaws-sdk-go

解决方案


不查看的实现,当您尝试解组到自定义接口时dynamodbattribute.UnmarshalMap,最终将失败。这不起作用,因为运行时无法知道要解组的底层结构。UnmarshalStatus

这是一个类似设置的 Playground 示例,仅json.

即使目视检查您的 json,您也无法确定 "message": {"S": "Completed"} 是成功还是错误。

您应该用结构(如下所示)甚至 a替换Statusin以使 unmarshal 工作map[string]Statusmap[string]string

{
    Message string
}

根据我之前分享的失败示例,是使其工作的方法之一。


推荐阅读