質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
date

dateは、date型や日付に関する関数や処理についてのタグです

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1894閲覧

Golang API/time.TimeオブジェクトのUnmarshalに関する質問

Yuta_Hayashi

総合スコア2

date

dateは、date型や日付に関する関数や処理についてのタグです

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2022/01/07 15:06

Golang API/time.TimeオブジェクトのUnmarshalに関する質問

Golangを最近始めたのですが、どうもUnmarshalがうまくいかず、調べても解決できなかったため質問させてください。

POSTMANを使いPOSTメソッドでデータを送信しています。

POST methodのFunction

go

1""" 2controllers.goのPOST Methodの関数 3""" 4func CreateProblem(w http.ResponseWriter, r *http.Request) { 5 CreateProblem := &models.Problem{} 6 body, err := ioutil.ReadAll(r.Body) 7 if err != nil { 8 return 9 } 10 fmt.Println(string(body))      ------ (1) 11 utils.ParseBody(r, CreateProblem) 12 b := CreateProblem.CreateProblem() 13 fmt.Println("printing DT") 14 fmt.Println(b.FinishedDT)                  ------ (2) 15 res, _ := json.Marshal(b) 16 w.WriteHeader(http.StatusOK) 17 w.Write(res) 18}

console

1controllers.goの(1)を実行後(POSTMANから実際に送ったデータ)は以下がプリント 2{ 3 "number": 122, 4 "title": "String Manupulation", 5 "difficulty": "easy", 6 "date": "2022-01-01" 7} 8Unmarshalされた後の日付はこのようなものをプリント 90001-01-01 00:00:00 +0000 UTC

このUnmarshalでPOSTMANで指定した"2022-01-01"が返ってこないのがとても不思議です。ネットで調べた上で、time.TimeをどのようにUnmarshalするか試行錯誤しましたが、特にParsebodyのReadAllでbodyをstringにしたのちどのようにすれば良いのかがわからないです。CreatedDateを追加するというソースは出てきましたが、僕がやりたいのは日にちとフォーマットを指定したdate: "yyyy-mm-dd"を返すというものです。

また、model.go, unmarshalしているutils.goは以下のようになっております。

go

1""" 2utils.goの中身 3""" 4func ParseBody(r *http.Request, x interface{}) { 5 if body, err := ioutil.ReadAll(r.Body); err == nil { 6 if err := json.Unmarshal([]byte(body), x); err != nil { 7 return 8 } 9 } 10}

go

1""" 2model.goの中身 3""" 4var db *gorm.DB 5 6type Problem struct { 7 gorm.Model 8 Number int `gorm:"" json:"number"` 9 Title string `json:"title"` 10 Difficulty string `json:"difficulty"` 11 FinishedDT Date `json:"date"` 12} 13 14type Date struct { 15 time.Time 16} 17 18func init() { 19 config.Connect() 20 db = config.GetDB() 21 // automigrate empty problem 22 db.AutoMigrate(&Problem{}) 23} 24 25// functions to communicate with database 26 27func (b *Problem) CreateProblem() *Problem { 28 // gorm function 29 db.NewRecord(b) 30 db.Create(&b) 31 return b 32}

現在このような構成でプロジェクトがあります。

(RESTfulAPI) ├── (cmd) │ └── main.go │ ├── (pkg) │ ├── (config) │ └──── app.go │ │ ├── (controllers) │ └──── controllers.go │ │ ├── (models) │ └──── model.go │ │ ├── (routes) │ └──── route.go │ │ ├── (utils) │ └──── utils.go │ ├── go.mod └── go.sum

どうぞ宜しくおねがいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

GoのJSONデコーダはtime.Time型に対してはtime.RFC3339という書式で書かれた文字列でなければいけません。
この日時のパースに成功する文字列の場合のみデコードに成功します。
(失敗した場合はゼロ値になります)

https://go.dev/play/p/qrcd4wXjCsA

go

1// You can edit this code! 2// Click here and start typing. 3package main 4 5import ( 6 "encoding/json" 7 "fmt" 8 "time" 9) 10 11type Problem struct { 12 FinishedDT Date `json:"date"` 13} 14 15type Date struct { 16 time.Time 17} 18 19const body = ` 20{ 21 "date": "2021-01-08T00:00:00+09:00" 22} 23` 24 25func main() { 26 var p *Problem 27 b := []byte(body) 28 if err := json.Unmarshal(b, &p); err != nil { 29 } 30 fmt.Printf("%v", p) 31}

ここを意図した書式の文字列でデコードさせたい場合はカスタムのUnmashalerを実装しなくてはなりません。

このjson.Unmarshalerを実装した型は標準のUnmarshal処理ではなく、この実装を優先的に使ってJSONのデコードを行います。

https://go.dev/play/p/BRbtRfN5x5_B

go

1package main 2 3import ( 4 "encoding/json" 5 "fmt" 6 "time" 7) 8 9type Problem struct { 10 FinishedDT *Date `json:"date"` 11} 12 13type Date struct { 14 time.Time 15} 16 17func (d *Date) UnmarshalJSON(b []byte) error { 18 v, err := time.Parse(`"2006-01-02"`, string(b)) 19 if err != nil { 20 return err 21 } 22 d.Time = v 23 return nil 24} 25 26const body = ` 27{ 28 "date": "2021-01-08" 29} 30` 31 32func main() { 33 var p *Problem 34 b := []byte(body) 35 if err := json.Unmarshal(b, &p); err != nil { 36 } 37 fmt.Printf("%v", p) 38}

投稿2022/01/08 01:03

編集2022/01/08 07:44
nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobonobo

2022/01/08 01:07

そして、元のコードでもこのコードでもjson.Unmarshalが返すエラーを見ていれば、日付のパースに失敗していたことはわかるはずです。
Yuta_Hayashi

2022/01/10 09:58

返信が遅くなってしまいまして、大変申し訳ございません。そしてとても親切なご回答ありがとうございました。調べても解決できなかったのは”このjson.Unmarshalerを実装した型は標準のUnmarshal処理ではなく、この実装を優先的に使ってJSONのデコードを行います。” を理解していなかったことでした。おかげさまでDateをフォーマットすることができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問