如何解组 map[string]*dynamodb.AttributeValue?

huangapple go评论80阅读模式
英文:

How to unmarshal map[string]*dynamodb.AttributeValue?

问题

我正在查询一个 DynamoDB 表,并需要对查询结果进行 UnmarshalMap,即将记录转换为 JSON 格式。

[{"movie":"Joker","year":"2019"}]

或者类似这样的格式:

[{"movie":"Joker","year":"2019"}, {"movie":"Cruella","year":"2021"}]

结构体定义如下:

type Movies struct {
   Movie string `json:"movie" bson:"movie" dynamodbav:"movie"`   
   Year  string `json:"year" bson:"year" dynamodbav:"year"`   
}

type Database struct {
    User    string    `json:"user" bson:"user" dynamodbav:"user"`   
    List    []*Movies `json:"movies" bson:"movies" dynamodbav:"movies"`
}

listOfMovies := Database{}

if err := dynamodbattribute.UnmarshalMap(tableOutput.Item, &listOfMovies); err != nil {
		log.Println(err)
		return nil, err
}

return listOfMovies.List, nil

tableOutput.Item 是一个包含数据库记录的映射,我没有收到任何错误,但是 Movies 列表为空。我不明白我做错了什么。UnmarshalMap 应该是这样工作的吗?

英文:

I am querying a DynamoDB table and need to UnmarshalMap i.e. query output.
The record in a table is JSON.

[{"movie":"Joker","year":"2019"}]

Or something like this

[{"movie":"Joker","year":"2019"}, {"movie":"Cruella","year":"2021"}]
type Movies struct {
   Movie string `json:"movie" bson:"movie" dynamodbav:"movie"`   
   Year  string `json:"year" bson:"year" dynamodbav:"year"`   
}

type Database struct {
    User    string    `json:"user" bson:"user" dynamodbav:"user"`   
    List    []*Movies `json:"movies" bson:"movies" dynamodbav:"movies"`
    
}


listOfMovies = Database{}

if err := dynamodbattribute.UnmarshalMap(tableOutput.Item, &listOfMovies); err != nil {
		log.Println(err)
		return nil, err
	}
return listOfMovies.List, nil

tableOutput.Item is a map and contains a record from database, I get no errors but the list of Movies is empty. I don't understand what I am doing wrong. Is this how UnmarshalMap should work?

答案1

得分: 1

为了管理您的场景,我编写了一个简单的示例程序,以便给您一个关于写入和读取过程的概述。下面是我示例应用程序的代码:

package main

import (
	"context"
	"encoding/json"
	"fmt"

	"dynamodbmovie/utils"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

var cfg *aws.Config

func main() {
	cfg, _ = utils.GetAwsConfig()
	dynaClient := dynamodb.NewFromConfig(*cfg)

	// 创建表
	dynaClient.CreateTable(context.TODO(), &dynamodb.CreateTableInput{
		TableName: aws.String("movies"),
		AttributeDefinitions: []types.AttributeDefinition{
			{
				AttributeName: aws.String("user"),
				AttributeType: types.ScalarAttributeTypeS,
			},
		},
		KeySchema: []types.KeySchemaElement{
			{
				AttributeName: aws.String("user"),
				KeyType:       types.KeyTypeHash,
			},
		},
		BillingMode: types.BillingModePayPerRequest,
	})

	defer func() {
		dynaClient.DeleteTable(context.TODO(), &dynamodb.DeleteTableInput{
			TableName: aws.String("movies"),
		})
	}()

	// 加载表
	dynaClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
		TableName: aws.String("movies"),
		Item: map[string]types.AttributeValue{
			"user":        &types.AttributeValueMemberS{Value: "user1"},
			"movies_list": &types.AttributeValueMemberS{Value: `[{"movie":"Joker","year":"2019"}, {"movie":"Cruella","year":"2021"}]`},
		},
	})

	// 读取表
	var filmString string
	res, _ := dynaClient.GetItem(context.TODO(), &dynamodb.GetItemInput{
		TableName: aws.String("movies"),
		Key: map[string]types.AttributeValue{
			"user": &types.AttributeValueMemberS{Value: "user1"},
		},
	})

	attributevalue.Unmarshal(res.Item["movies_list"], &filmString)
	myDb := &Database{
		User: "user1",
	}

	json.Unmarshal([]byte(filmString), &myDb.List)

	fmt.Println(len(myDb.List))
}

utils/models.go

package main

type Movies struct {
	Movie string `json:"movie"`
	Year  string `json:"year"`
}

type Database struct {
	User string    `json:"user"`
	List []*Movies `json:"movies"`
}

如您所见,除了json标签注释之外,不需要其他标签注释。为了满足您的需求,我将电影列表存储在 DynamoDB 中作为一个 JSON 字符串,因此您需要进行字符串的编组/解组操作,这很容易。然后,通过第二次解组,您可以将信息放入Database结构中。

请注意,为了示例的简洁性,我没有考虑错误处理和编写良好软件的原则。

英文:

To manage your scenario, I wrote down a trivial sample program to give you an overview of the writing and reading process. Below you can find the code for my sample application:

package main

import (
	"context"
	"encoding/json"
	"fmt"

	"dynamodbmovie/utils"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb"
	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

var cfg *aws.Config

func main() {
	cfg, _ = utils.GetAwsConfig()
	dynaClient := dynamodb.NewFromConfig(*cfg)

	// create table
	dynaClient.CreateTable(context.TODO(), &dynamodb.CreateTableInput{
		TableName: aws.String("movies"),
		AttributeDefinitions: []types.AttributeDefinition{
			{
				AttributeName: aws.String("user"),
				AttributeType: types.ScalarAttributeTypeS,
			},
		},
		KeySchema: []types.KeySchemaElement{
			{
				AttributeName: aws.String("user"),
				KeyType:       types.KeyTypeHash,
			},
		},
		BillingMode: types.BillingModePayPerRequest,
	})

	defer func() {
		dynaClient.DeleteTable(context.TODO(), &dynamodb.DeleteTableInput{
			TableName: aws.String("movies"),
		})
	}()

	// load table
	dynaClient.PutItem(context.TODO(), &dynamodb.PutItemInput{
		TableName: aws.String("movies"),
		Item: map[string]types.AttributeValue{
			"user":        &types.AttributeValueMemberS{Value: "user1"},
			"movies_list": &types.AttributeValueMemberS{Value: `[{"movie":"Joker","year":"2019"}, {"movie":"Cruella","year":"2021"}]`},
		},
	})

	// read table
	var filmString string
	res, _ := dynaClient.GetItem(context.TODO(), &dynamodb.GetItemInput{
		TableName: aws.String("movies"),
		Key: map[string]types.AttributeValue{
			"user": &types.AttributeValueMemberS{Value: "user1"},
		},
	})

	attributevalue.Unmarshal(res.Item["movies_list"], &filmString)
	myDb := &Database{
		User: "user1",
	}

	json.Unmarshal([]byte(filmString), &myDb.List)

	fmt.Println(len(myDb.List))
}

utils/models.go

package main

type Movies struct {
	Movie string `json:"movie"`
	Year  string `json:"year"`
}

type Database struct {
	User string    `json:"user"`
	List []*Movies `json:"movies"`
}

As you can see, there is no need for other tag annotation except the json ones. To accomplish your needs, I stored in DynamoDb the list of movies as a JSON string so you've to marshal/unmarshal to and from a string which is easy. Then, with a second unmarshal you can bring the information on the Database struct.
> Please note, that for the sake of example, I didn't take into consideration the error management and the principles for writing good software.

huangapple
  • 本文由 发表于 2022年11月1日 16:50:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/74273483.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定