1

I have a strange issue. I'm using echo package for routing. While I'm decoding json to struct I'm getting error parsing time \"\"2019-01-02\"\" as \"\"2006-01-02T15:04:05Z07:00\"\": cannot parse \"\"\" as \"T\""

my structs

VendorAgreement struct {
    ID                   primitive.ObjectID   `json:"id" bson:"_id"`
    StartDate            time.Time            `json:"start_date,date" bson:"start_date"`
    EndDate              time.Time            `json:"end_date,date" bson:"end_date"`
    CommissionPercentage float32              `json:"commission_percentage" bson:"commission_percentage"`
    Status               int                  `json:"status" bson:"status"`
    CreatedDate          time.Time            `json:"created_date" bson:"created_date"`
    Media                VendorAgreementMedia `json:"media" bson:"media"`
}

VendorAgreementMedia struct {
    MediaId     primitive.ObjectID `json:"mediaId" bson:"_id"`
    FileName    string             `json:"file_name" bson:"file_name"`
    SourcePath  string             `json:"source_path" bson:"source_path"`
    CreatedDate time.Time          `json:"created_date" bson:"created_date"`
}

My decoding step

var agreement VendorAgreement
err = json.NewDecoder(c.Request().Body).Decode(&agreement)

request body

 {
    "start_date":"2019-01-02",
    "end_date":"2020-05-06",
    "commission_percentage":10,
    "media":{
        "mediaId":"5cd1644cc57849f0761632b5"
    }
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
M14
  • 1,780
  • 2
  • 14
  • 31
  • 3
    you will need a custom json.Unmarshaler to extract the correct time. There is no way for the default unmarshaler to know your time format. I assume you are `YYYY-MM-DD`, but it could be `YYYY-DD-MM`. json.Unmarshal expects time format `time.RFC3339` – colm.anseo May 07 '19 at 13:31
  • 2
    see this [answer](https://stackoverflow.com/a/25088283/1218512) on how to create a CustomTime type to handle custom formats. – colm.anseo May 07 '19 at 13:32
  • I'll try and let you know – M14 May 07 '19 at 14:32

2 Answers2

2

You need to have a custom time type in order to unmarshal custom time format:

type Datetime struct {
    time.Time
}

func (t *Datetime) UnmarshalJSON(input []byte) error {
    strInput := strings.Trim(string(input), `"`)
    newTime, err := time.Parse("2006-01-02", strInput)
    if err != nil {
        return err
    }

    t.Time = newTime
    return nil
}

VendorAgreement struct {
    ID                   primitive.ObjectID   `json:"id" bson:"_id"`
    StartDate            Datetime             `json:"start_date,date" bson:"start_date"`
    EndDate              Datetime             `json:"end_date,date" bson:"end_date"`
    CommissionPercentage float32              `json:"commission_percentage" bson:"commission_percentage"`
    Status               int                  `json:"status" bson:"status"`
    CreatedDate          Datetime             `json:"created_date" bson:"created_date"`
    Media                VendorAgreementMedia `json:"media" bson:"media"`
}

VendorAgreementMedia struct {
    MediaId     primitive.ObjectID `json:"mediaId" bson:"_id"`
    FileName    string             `json:"file_name" bson:"file_name"`
    SourcePath  string             `json:"source_path" bson:"source_path"`
    CreatedDate Datetime           `json:"created_date" bson:"created_date"`
}
Alex Pliutau
  • 21,392
  • 27
  • 113
  • 143
  • This is working but in my mongo it is saving as `"start_date" : { "time" : ISODate("2019-01-02T00:00:00.000Z") }, "end_date" : { "time" : ISODate("2020-05-06T00:00:00.000Z") },` – M14 May 08 '19 at 05:34
  • This is so stupid on Google engineers part. No customization whatsoever. No API to pass the format. – TheRealChx101 Mar 20 '23 at 17:22
0

you can parse your date returned by mongo like this:

layout := "2006-01-02T15:04:05.999999999Z07:00"
str := "2019-01-02T00:00:00.000Z"
t, err := time.Parse(layout, str)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Println(t)
}