英文:
How to change struct tags by generics
问题
我需要创建一个带有动态标签的泛型结构体。
例如,我们有一个带有泛型的结构体 Phone[T]
和一个简单的结构体 Company
。
所以,Phone 可以属于 Company,这意味着我们的类型将是 Phone[Company]
。
type Company struct{}
type Phone[T any] struct{
number string `json:"phone_number"`
}
让我们创建一个新的变量 Phone[Company]
phone1 := Phone[Company]{
number: "+18888888888"
}
序列化后的 phone1
的输出结果为
{
"phone_number": "+18888888888"
}
问题
如何动态设置结构体 Phone[T]
类型字段的标签,以接收类似于 company_phone_number
而不是 phone_number
的 JSON 数据?
如何在 Golang 的标签中使用泛型类型?
例如:
type Phone[T any] struct{
number string `json:"${T 或 T 类型的复制品名称}_phone_number"`
}
英文:
I need to create struct with generics with dynamic tags
> e.g. We have one struct with generics Phone[T]
and simple struct Company
So Phone can belongs to Company and that means our type would be Phone[Company]
type Company struct{}
type Phone[T any] struct{
number string `json:"phone_number"`
}
Lets create new variable Phone[Company]
phone1 := Phone[Company]{
number: "+18888888888"
}
Output of serialized phone1
is
{
"phone_number": "+18888888888"
}
Question
How to set struct Phone[T]
type field tags dynamically to receive json like company_phone_number
instead of phone_number
?
How can i use generic types in golang tags?
e.g.
type Phone[T any] struct{
number string `json:"${T or replica name of T type e.t.c}_phone_number"`
}
答案1
得分: 4
你只能通过使用反射在运行时重新构建你的结构体来实现这一点。有一个专门的包可以做到这一点(我没有尝试过)这里。
但是,我建议你为结构体编写一个自定义的MarshalJSON方法,根据变量的类型处理不同的情况。
package main
import (
"encoding/json"
"errors"
"fmt"
)
type Phone[T any] struct {
variableType T
Number string
}
func (p Phone[T]) MarshalJSON() ([]byte, error) {
switch any(p.variableType).(type) {
case Company:
return json.Marshal(&struct {
Number string `json:"company_phone_number"`
}{
Number: p.Number,
})
case Company2:
return json.Marshal(&struct {
Number string `json:"company2_phone_number"`
}{
Number: p.Number,
})
}
return []byte{}, errors.New("Invalid type")
}
type Company struct {
}
type Company2 struct {
}
func main() {
p := Phone[Company]{
Number: "123",
}
p2 := Phone[Company2]{
Number: "321",
}
data1, _ := json.Marshal(p)
data2, _ := json.Marshal(p2)
fmt.Println(p, string(data1))
fmt.Println(p2, string(data2))
}
如果你想避免使用switch语句,你可以使用reflect.TypeOf(p.variableType).Name()
来获取变量的类型,但是你需要编写一个自定义的JSON marshaler来表示带有自定义JSON标签的字节切片。
英文:
You can do it only if you rebuild your struct on-the-fly with reflect. There is a package for this (I didn't try it) here.
But instead I recommend you to write a custom MarshalJSON method for the struct which handles the cases based on the type of the variable.
package main
import (
"encoding/json"
"errors"
"fmt"
)
type Phone[T any] struct {
variableType T
Number string
}
func (p Phone[T]) MarshalJSON() ([]byte, error) {
switch any(p.variableType).(type) {
case Company:
return json.Marshal(&struct {
Number string `json:"company_phone_number"`
}{
Number: p.Number,
})
case Company2:
return json.Marshal(&struct {
Number string `json:"company2_phone_number"`
}{
Number: p.Number,
})
}
return []byte{}, errors.New("Invalid type")
}
type Company struct {
}
type Company2 struct {
}
func main() {
p := Phone[Company]{
Number: "123",
}
p2 := Phone[Company2]{
Number: "321",
}
data1, _ := json.Marshal(p)
data2, _ := json.Marshal(p2)
fmt.Println(p, string(data1))
fmt.Println(p2, string(data2))
}
If you want to avoid the switch you can get the variable type with reflect.TypeOf(p.variableType).Name()
but then you have to write a custom JSON marshaler to represent the byte slice with the custom json tags.
答案2
得分: 0
这是要翻译的内容:
这是不可能的!
对于你的情况,你可以重新设计你的架构。
英文:
It's imposible!
For your case you can redesign your architecture
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论