GOOGLE ADS

martes, 19 de abril de 2022

gin/golang gin-gonic no analiza el tiempo. ¿Tiempo correctamente para unix json?

I cannot find the way to execute this code properly with UNIX:

package main
import (
"time"
"github.com/gin-gonic/gin"
"net/http"
)
type Things struct {
Name string `json:"name"`
OneDay time.Time `json:"oneDay"`
}
type Example struct {
Things []Things `json:"things"`
Something int `json:"something"`
}
func TestGinGo(c *gin.Context) {
var example Example
c.BindJSON(&example)
c.JSON(http.StatusOK, gin.H{"data": example})
}
func main() {
r:= gin.Default()
r.POST("/", TestGinGo)
r.Run("0.0.0.0:8080")
}

Llamo a este punto final así:

curl --location --request POST 'localhost:8080' \
--header 'Content-Type: application/json' \
--data-raw '{
"things": [{
"name": "bling",
"oneDay": "2020-01-01T00:00:00Z"
}],
"something": 2
}'

La respuesta es correcta:

{
"data": {
"things": [
{
"name": "bling",
"oneDay": "2020-01-01T00:00:00Z"
}
],
"something": 2
}
}

Ahora cambio un poco el código para que funcione con UNIX así:

package main
import (
"time"
"github.com/gin-gonic/gin"
"net/http"
)
type Things struct {
Name string `json:"name"`
OneDay time.Time `json:"oneDay" time_format:"unix"`
}
type Example struct {
Things []Things `json:"things"`
Something int `json:"something"`
}
func TestGinGo(c *gin.Context) {
var example Example
c.BindJSON(&example)
c.JSON(http.StatusOK, gin.H{"data": example})
}
func main() {
r:= gin.Default()
r.POST("/", TestGinGo)
r.Run("0.0.0.0:8080")
}

Y lo llamo así:

curl --location --request POST 'localhost:8080' \
--header 'Content-Type: application/json' \
--data-raw '{
"things": [{
"name": "bling",
"oneDay": 1589898758007
}],
"something": 2
}'

Y me sale este error ahora (400 mal formato):

{"data":{"things":[{"name":"bling","oneDay":"0001-01-01T00:00:00Z"}],"something":0}}

Entro a la librería... y veo que ahí está el código para usar "unix":

https://github.com/gin-gonic/gin/blob/master/binding/form_mapping.go#L272

Realmente me gustaría usar Unix, porque muchos idiomas no necesitan una biblioteca para usar Unix, y no quiero forzar el uso de un formato específico por parte del consumidor... Y no veo dónde me estoy perdiendo la pelota aquí...


Solución del problema

  • time_formatla etiqueta solo se usa en el formenlace, no json;

  • Puede usar las funciones Marshal y Unmarshal personalizadas (consulte https://pkg.go.dev/encoding/json#example-package-CustomMarshalJSON )

  • package main
    import (
    "encoding/json"
    "github.com/gin-gonic/gin"
    "log"
    "net/http"
    "time"
    )
    type myTime time.Time
    func (mt *myTime) UnmarshalJSON(bs []byte) error {
    var timestamp int64
    err:= json.Unmarshal(bs, &timestamp)
    if err!= nil {
    return err
    }
    *mt = myTime(time.Unix(timestamp/1000, timestamp%1000*1e6))
    return nil
    }
    func (mt myTime) MarshalJSON() ([]byte, error) {
    timestamp:= time.Time(mt).UnixNano() / 1e6
    log.Println(time.Time(mt).UnixNano())
    return json.Marshal(timestamp)
    }
    type Timestamp struct {
    OneDay myTime `json:"oneDay" form:"oneDay"`
    AnotherDay time.Time `json:"anotherDay" form:"anotherDay" time_format:"unix"`
    }
    func parseTime(c *gin.Context) {
    var example Timestamp
    if err:= c.Bind(&example); err!= nil {
    log.Printf("bind timestamp error: %s", err)
    }
    c.JSON(http.StatusOK, gin.H{"data": example})
    }
    func main() {
    r:= gin.Default()
    r.POST("/time", parseTime)
    r.Run("0.0.0.0:8080")
    }

  • enviar como json

  • curl --location --request POST 'localhost:8080/time' \
    --header 'Content-Type: application/json' \
    --data '{
    "oneDay": 1589898758007,
    "anotherDay": "1589898758"
    }'

    oneDayes correcto, anotherDayno funciona

    {"data":{"oneDay":1589898758007,"anotherDay":"0001-01-01T00:00:00Z"}}

  • enviar como formulario

  • curl --location --request POST 'localhost:8080/time' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data 'oneDay=1589898758007&anotherDay=1589898758'

    ambos tienen razón

    {"data":{"oneDay":1589898758007,"anotherDay":"2020-05-19T22:32:38+08:00"}}

    No hay comentarios.:

    Publicar un comentario

    Flutter: error de rango al acceder a la respuesta JSON

    Estoy accediendo a una respuesta JSON con la siguiente estructura. { "fullName": "FirstName LastName", "listings...