英文:
hh:mm:ss to time.Time while parsing from JSON in Go
问题
我有一个无法更改的结构体,并且在一个单独的JSON文件中有一个包含这些结构体的数组。
我可以轻松地从JSON文件中解析数据,但是在同一个字段中存在不匹配的类型:
(main.go)
import "time"
type SomeType struct {
name string `json: "name"`
time time.Time `json: "someTime"`
}
(someData.json)
[
{
"name": "some name",
"someTime": "15:20:00"
},
{
"name": "some other name",
"someTime": "23:15:00"
}
]
如果"time"字段是字符串类型,我可以简单地使用json.Unmarshal将所有数据从JSON解析为[]SomeType,但由于类型不匹配,我找不到正确的方法来做到这一点。
英文:
I have a struct that I can't change and an array of these structs in a separate JSON file.
I could have parsed data from JSON file easily, but there are mismatched types in same fields:
(main.go)
import "time"
type SomeType struct {
name string `json: "name"`
time time.Time `json: "someTime"`
}
(someData.json)
[
{
"name": "some name",
"someTime": "15:20:00"
},
{
"name": "some other name",
"someTime": "23:15:00"
}
]
If "time" field was a type of a string, I would simply use json.Unmarshal and parse all of the data from json into []SomeType, but since types mismatch, I can't find a way to do it correctly.
答案1
得分: 2
你应该在你的结构体中添加UnmarshalJSON方法。
type SomeType struct {
Name string `json:"name"`
Time time.Time `json:"someTime"`
}
func (st *SomeType) UnmarshalJSON(data []byte) error {
type parseType struct {
Name string `json:"name"`
Time string `json:"someTime"`
}
var res parseType
if err := json.Unmarshal(data, &res); err != nil {
return err
}
parsed, err := time.Parse("15:04:05", res.Time)
if err != nil {
return err
}
now := time.Now()
st.Name = res.Name
st.Time = time.Date(now.Year(), now.Month(), now.Day(), parsed.Hour(), parsed.Minute(), parsed.Second(), 0, now.Location())
return nil
}
英文:
You should add the UnmarshalJSON method to your struct
type SomeType struct {
Name string `json:"name"`
Time time.Time `json:"someTime"`
}
func (st *SomeType) UnmarshalJSON(data []byte) error {
type parseType struct {
Name string `json:"name"`
Time string `json:"someTime"`
}
var res parseType
if err := json.Unmarshal(data, &res); err != nil {
return err
}
parsed, err := time.Parse("15:04:05", res.Time)
if err != nil {
return err
}
now := time.Now()
st.Name = res.Name
st.Time = time.Date(now.Year(), now.Month(), now.Day(), parsed.Hour(), parsed.Minute(), parsed.Second(), 0, now.Location())
return nil
}
答案2
得分: 1
我认为你应该定义一个自定义的时间类型,并使用自定义的解组器,如下所示:
type CustomTime struct {
time.Time
}
func (t *CustomTime) UnmarshalJSON(b []byte) error {
formattedTime, err := time.Parse("\"15:04:05\"", string(b))
t.Time = formattedTime
return err
}
然后,你可以创建另一个结构体,基本上与你现有的结构体相同,只是它使用你的自定义时间类型,而不是原始的time.Time
:
type SameTypeWithDifferentTime struct {
Name string `json:"name"`
SomeTime CustomTime `json:"someTime"`
}
func (s SameTypeWithDifferentTime) ToOriginal() SomeType {
return SomeType{
Name: s.Name,
SomeTime: s.SomeTime.Time,
}
}
其余的过程非常简单,你只需将 JSON 反序列化为新类型,并使用 ToOriginal()
方法将其转换为原始结构体。还有一点需要注意的是,你没有导出结构体字段。
英文:
I think you should define a custom time type, with a custom unmarshaller as follows:
type CustomTime struct {
time.Time
}
func (t *CustomTime) UnmarshalJSON(b []byte) error {
formattedTime, err := time.Parse(`"15:04:05"`, string(b))
t.Time = formattedTime
return err
}
And have another struct, which is basically the exact struct you have, instead it uses your custom time type rather than the original struct which uses time.Time
:
type SameTypeWithDifferentTime struct {
Name string `json:"name"`
SomeTime CustomTime `json:"someTime"`
}
func (s SameTypeWithDifferentTime) ToOriginal() SomeType {
return SomeType {
Name: s.Name,
SomeTime: s.SomeTime.Time,
}
}
The rest of the process is pretty straight forward, you just deserialize your json to the new type, and use ToOriginal()
receiver function to convert it to your original struct. Another point to mention here is that your not exporting your struct fields.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论