英文:
Transform values when umarshaling
问题
给定以下代码,是否可以在解组时转换名字?假设我希望始终将其转换为小写,无论实际的 JSON 中是否包含它。
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func main() {
jsonText := GetJsonFromSomewhere()
var v Person
json.Unmarshal(jsonText, &v)
}
可以在解组时转换名字。你可以使用自定义的解组方法来实现这一点。首先,你需要创建一个结构体类型,该类型包含要解组的字段。然后,你可以为该结构体类型定义一个自定义的 UnmarshalJSON
方法,该方法在解组时会被调用。
下面是一个示例代码,演示如何在解组时将 FirstName
字段转换为小写:
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func (p *Person) UnmarshalJSON(data []byte) error {
type Alias Person // 创建一个别名类型,以便在 Unmarshal 过程中使用
aux := &struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}{
FirstName: strings.ToLower(p.FirstName), // 将 FirstName 转换为小写
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
*p = Person(*aux) // 将转换后的值赋给原始的 Person 结构体
return nil
}
func main() {
jsonText := GetJsonFromSomewhere()
var v Person
json.Unmarshal(jsonText, &v)
}
在上面的代码中,我们创建了一个 Alias
类型,它是 Person
类型的别名。在 UnmarshalJSON
方法中,我们首先创建了一个辅助结构体 aux
,它具有与 Person
结构体相同的字段。然后,我们将 FirstName
字段转换为小写,并将其赋值给 aux
结构体。接下来,我们使用 json.Unmarshal
将 JSON 数据解组到 aux
结构体中。最后,我们将转换后的值赋给原始的 Person
结构体。
这样,无论实际的 JSON 中 FirstName
字段的值是什么,它都会在解组时被转换为小写。
英文:
Given the code below, is it possible to transform first name while it's being unmarshaled? Say I want to always have it be lowercase whether it is in the actual json or not.
type Person struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func main() {
jsonText := GetJsonFromSomewhere()
var v Person
json.Unmarshal(jsonText, &v)
}
答案1
得分: 4
一种方法是创建一个自定义类型,实现encoding/json
包中的Unmarshaler
接口。这是该接口的链接。任何实现了Unmarshaler
接口的类型都可以在进行JSON解组时用作结构字段的类型。在解组过程中,encoding/json
将使用你实现的接口的UnmarshalJSON
函数将JSON字节转换为字段类型。
因此,你可以编写一个UnmarshalJSON
函数,其中包括将字符串值转换为小写的操作。
以下是一个示例:
type LowerCaseString string
func (l *LowerCaseString) UnmarshalJSON(bytes []byte) error {
lowerCasedString := strings.ToLower(string(bytes))
*l = LowerCaseString(lowerCasedString)
return nil
}
然后,在用于JSON映射的结构中,你可以使用自定义类型而不是string
:
type Person struct {
FirstName LowerCaseString `json:"first_name"`
LastName LowerCaseString `json:"last_name"`
}
如果你将JSON解组到此结构中,FirstName和LastName的值将被转换为小写(还要注意,你需要将它们转换回string
以将其用作string
)。
testJSON := `{"first_name" : "TestFirstNAME", "last_name": "TestLastNAME"}`
var result Person
err := json.Unmarshal([]byte(testJSON), &result)
if err != nil { /*处理错误*/ }
fmt.Println(result.FirstName) // 输出 "testfirstname"
var stringLastName string
stringLastName = string(result.LastName) // 需要将LowerCaseString转换为string类型
fmt.Println(stringLastName) // 输出 "testlastname"
英文:
One way to do this is to create a custom type that implements the Unmarshaler
interface from the encoding/json
package. Here's a link to this interface. Any type which implements Unmarshaler
can be used as the type of a struct field when doing JSON unmarshalling. When doing the unmarshalling, encoding/json
will use your implementation of the interface's UnmarshalJSON
function to convert the JSON bytes to the field type.
So you could write an UnmarshalJSON
function which includes changing the string values to lowercase.
Here's an example of what that could look like:
type LowerCaseString string
func (l *LowerCaseString) UnmarshalJSON(bytes []byte) error {
lowerCasedString := strings.ToLower(string(bytes))
*l = LowerCaseString(lowerCasedString)
return nil
}
Then, in your struct for JSON mapping, you can use your custom type instead of string
:
type Person struct {
FirstName LowerCaseString `json:"first_name"`
LastName LowerCaseString `json:"last_name"`
}
If you unmarshal into this struct, the values of FirstName and LastName will be lowercased (also note that you'll need to type convert them back to string
to use them as string
s).
testJSON := `{"first_name" : "TestFirstNAME", "last_name": "TestLastNAME"}`
var result Person
err := json.Unmarshal([]byte(testJSON), &result)
if err != nil { /*handle the error*/ }
fmt.Println(result.FirstName) // prints "testfirstname"
var stringLastName string
stringLastName = string(result.LastName) // need to type convert from LowerCaseString to string
fmt.Println(stringLastName) // prints "testlastname"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论