将hh:mm:ss转换为time.Time类型时,可以使用Go语言中的JSON解析功能。

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

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
}

GoPlay

英文:

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
}

GoPlay

答案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.

huangapple
  • 本文由 发表于 2022年7月30日 19:02:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/73175042.html
匿名

发表评论

匿名网友

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

确定