英文:
What's the correct/agreed way to partial update REST API in Golang
问题
让我们假设我们有一个结构体:
type Person struct {
ID string `json:"id"`
Name string `json:"name"`
DOB string `json:"dob"`
Status string `json:"status"` // enabled/disabled
Address string `json:"address"`
DataRetentionPeriod uint32 `json:"dataRetentionPeriod"`
PrimaryContact `json:"primaryContact"`
}
type PrimaryContact struct {
Name string `json:"name"`
Phone string `json:"phone"`
Email string `json:"email"`
}
我们希望能够根据需要部分更新这个结构体。例如,我们只想更改他的Address
、DataRetentionPeriod
或PrimaryContact
。我们正在使用DynamoDb
,因此在发送更新时,最终产品需要是map[string]interface{}
。
在Go中,最佳/正确的方法是什么?
以下是我们有的几种方法:
1) 每次发送一个新的完整主体。这样可以解决问题,但问题是客户端需要在网络上发送比必要数据更多的数据。因此,我们希望避免这种情况。
2) 我们可以将原始结构体转换为指针,然后使用reflect
检查空值,然后将其转换为map[string]interface{}
以发送到SDK。
3) 使用类似于structs
的包来构建一个只包含所需字段的来自API的新结构体。
4) 将主体解组为map[string]json.RawMessage
,然后映射到项目并验证正确/必需的字段,然后将其转换为map[string]interface{}
。
还有其他几种方法,但没有一种方法看起来很简洁。
请指导如何在Golang中使用部分更新进行REST API。
谢谢。
英文:
Let's say we have a struct
type Person struct {
ID string `json:"id"`
Name string `json:"name"`
DOB string `json:"dob"`
Status string `json:"status"` // enabled/disabled
Address string `json:"address"`
DataRetentionPeriod uint32 `json:"dataRetentionPeriod"`
PrimaryContact `json:"primaryContact"`
}
type PrimaryContact struct {
Name string `json:"name"`
Phone string `json:"phone"`
Email string `json:"email"`
}
We want to be able to partial update this struct as we see fit. For example, we want to only change his Address
or DataRetentionPeriod
or PrimaryContact
. We are using DynamoDb
so the end product needs to be map[string]interface{}
when sending the updates.
What is the best/correct way of doing this in Go?
These are the following approaches we have:
1) Send a new complete body every time. This will resolve the issue but the problem is the client needs to send more data than necessary over the network. So we want to avoid this.
2) We can turn the original struct into pointers and then check the nil values using reflect
and then transform it into map[string] interface
to send to the SDK
3) Use a package like structs
to build a new struct that's coming from the API with only the fields required
4) Unmarshal the body into a map[string]json.RawMessage
and then map over the items and verify the correct/required fields and then transform it into map[string]interface
A few others but none of them feel clean.
Please advise on "best" way to do partial updates using Golang for REST APIs.
Thank you.
答案1
得分: 1
有很多方法可以实现你提到的需求。
gRPC
使用了一种适用于我的用例的方法。基本上是使用 PATCH
请求,其中请求包含两个结构体:你的数据结构和一个更新掩码([]string
),掩码指定了将要更新的内容。
考虑以下示例:
type Person struct {
ID string `json:"id"`
Name string `json:"name"`
DOB string `json:"dob"`
Status string `json:"status"` // enabled/disabled
Address string `json:"address"`
DataRetentionPeriod uint32 `json:"dataRetentionPeriod"`
PrimaryContact `json:"primaryContact"`
}
type PrimaryContact struct {
Name string `json:"name"`
Phone string `json:"phone"`
Email string `json:"email"`
}
// PersonRequest 将通过 HTTP PATCH 方法在你的服务中接受
// 如果 `updateMask` 被填充,它将指定客户端所需的更改
// 一个请求的示例可能如下所示:
//
// myUpdateRequest := PersonRequest{
// Person{Name: "joe", DOB: "01-01-1970", PrimaryContact: PrimaryContact{Phone: "+12223334444"}},
// UpdateMask: []string{"name", "dob", "primaryContact.phone"},
// }
//
type PersonRequest struct {
Person Person `json:"person"`
UpdateMask []string `json:"updateMask"`
}
以上是代码的翻译部分。
英文:
There are many approaches as you noted.
gRPC
uses an approach that works well for my use cases. Basically a PATCH
where the request contains two structs your data struct and an update mask ([]string
), the mask specifies what will be updated.
consider this
type Person struct {
ID string `json:"id"`
Name string `json:"name"`
DOB string `json:"dob"`
Status string `json:"status"` // enabled/disabled
Address string `json:"address"`
DataRetentionPeriod uint32 `json:"dataRetentionPeriod"`
PrimaryContact `json:"primaryContact"`
}
type PrimaryContact struct {
Name string `json:"name"`
Phone string `json:"phone"`
Email string `json:"email"`
}
// PersonRequest would be accepted via http PATCH method in you service
// the `updateMask` if populated would specify the client's desired changes
// an example of Request might look like this
//
// myUpdateRequest := PersonRequest{
// Person{Name:"joe",DOB:"01-01-1970",PrimaryContact: PrimaryContact{Phone: "+12223334444"}},
// UpdateMask: []string{"name", "dob", "primaryContact.phone"},
// }
//
Type PersonRequest struct {
Person Person `json:"person"`
UpdateMask []string `json:"updateMask"`
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论