在PostgreSQL中,我有一个名为的表surveys。
surveys
CREATE TABLE SURVEYS( SURVEY_ID UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(), SURVEY_NAME VARCHAR NOT NULL, SURVEY_DESCRIPTION TEXT, START_PERIOD TIMESTAMP, END_PERIOD TIMESTAMP );
如您所见SURVEY_ID,SURVEY_NAME列为NOT NULL。
SURVEY_ID
SURVEY_NAME
NOT NULL
在Go中,我想通过POST请求在该表中创建新条目。我像这样发送JSON对象:
POST
{ "survey_name": "NAME", "survey_description": "DESCRIPTION", "start_period": "2019-01-01 00:00:00", "end_period": "2019-02-28 23:59:59" }
不幸的是,它引发了奇怪的 错误 :
parsing time ""2019-01-01 00:00:00"" as ""2006-01-02T15:04:05Z07:00"": cannot parse " 00:00:00"" as "T"
我在哪里犯错误以及如何解决我的问题?
models / surveys.go:
import ( "database/sql" "time" ) type NullTime struct { time.Time Valid bool } type Survey struct { ID int `json:"survey_id"` Name string `json:"survey_name"` Description sql.NullString `json:"survey_description"` StartPeriod NullTime `json:"start_period"` EndPeriod NullTime `json:"end_period"` }
控制器/surveys.go:
var CreateSurvey = func(responseWriter http.ResponseWriter, request *http.Request) { // Initialize variables. survey := models.Survey{} var err error // The decoder introduces its own buffering and may read data from argument beyond the JSON values requested. err = json.NewDecoder(request.Body).Decode(&survey) if err != nil { log.Println(err) utils.ResponseWithError(responseWriter, http.StatusInternalServerError, err.Error()) return } defer request.Body.Close() // Execute INSERT SQL statement. _, err = database.DB.Exec("INSERT INTO surveys (survey_name, survey_description, start_period, end_period) VALUES ($1, $2, $3, $4);", survey.Name, survey.Description, survey.StartPeriod, survey.EndPeriod) // Shape the response depending on the result of the previous command. if err != nil { log.Println(err) utils.ResponseWithError(responseWriter, http.StatusInternalServerError, err.Error()) return } utils.ResponseWithSuccess(responseWriter, http.StatusCreated, "The new entry successfully created.") }
该错误已说明出了什么问题:
将时间“” 2019-01-01 00:00:00“”解析为“” 2006-01-02T15:04:05Z07:00“”:无法将“ 00:00:00”“解析为” T“
您正在传递,"2019-01-01 00:00:00"而它期望使用不同的时间格式,即RFC3339(UnmarshalJSON的默认值)。
"2019-01-01 00:00:00"
为了解决这个问题,您要么希望以期望的格式传递时间,要么像这样"2019-01-01T00:00:00Z00:00"定义自己的类型CustomTime:
"2019-01-01T00:00:00Z00:00"
CustomTime
const timeFormat = "2006-01-02 15:04:05" type CustomTime time.Time func (ct *CustomTime) UnmarshalJSON(data []byte) error { newTime, err := time.Parse(timeFormat, strings.Trim(string(data), "\"")) if err != nil { return err } *ct = CustomTime(newTime) return nil } func (ct *CustomTime) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("%q", time.Time(*ct).Format(timeFormat))), nil }
小心,您可能还需要实现Valuer和Scanner接口,以便在数据库中进行解析时,如下所示:
Valuer
Scanner
func (ct CustomTime) Value() (driver.Value, error) { return time.Time(ct), nil } func (ct *CustomTime) Scan(src interface{}) error { if val, ok := src.(time.Time); ok { *ct = CustomTime(val) } else { return errors.New("time Scanner passed a non-time object") } return nil }
转到Playground示例。