Проблема парсинга значений типа PostgreSQL TIMESTAMP - PullRequest
0 голосов
/ 28 февраля 2019

В PostgreSQL у меня есть таблица с именем 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.

В Go,Я хочу создать новую запись в этой таблице по запросу POST.Я отправляю объект JSON следующим образом:

{
    "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 / surveyys.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"`
}

controllers / surveyys.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.")
}

1 Ответ

0 голосов
/ 28 февраля 2019

Ошибка уже говорит о том, что не так:

время разбора "" 2019-01-01 00:00:00 "" as "" 2006-01-02T15: 04: 05Z07: 00"": невозможно проанализировать "00:00:00" "как" T "

Вы передаете "2019-01-01 00:00:00", в то время как он ожидает другой формат времени, а именно RFC3339 ( UnmarshalJSON по умолчанию ).

Чтобы решить эту проблему, вы хотите либо передать время в ожидаемом формате "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 для времени, которое нужно проанализировать в базе данных и из нее, что-то вроде следующего:

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
}

Go Playground пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...