jsongomodelgo-echo

error: json: unsupported type: func() time.Time in Golang


i am new in golang, just try some API in Echo Framework and got some error.

My Models :

package models

import (
    "net/http"
    "quotes/db"
)

type Quote struct {
    Id          int    `json:"id"`
    Title       string `json:"title"`
    Description string `json:"description"`
}

func GetAll() (Response, error) {
    var quotes Quote
    var res Response

    ctx := db.Init()

    ctx.Find(&quotes)

    res.Status = http.StatusOK
    res.Message = "Success"
    res.Data = ctx

    return res, nil
}

My Schema table

package schema

type Quotes struct {
    Id          int    `json:"id"`
    Title       string `json:"title"`
    Description string `json:"description"`
}

My Response type for Api

package models

type Response struct {
    Status  int         `json:"status"`
    Message string      `json:"message"`
    Data    interface{} `json:"data"`
}

i tried to add this in Models and Schema :

CreatedAt   time.Time `gorm:"type:timestamp" json:"created_at,string,omitempty"`
UpdatedAt   time.Time `gorm:"type:timestamp" json:"updated_at,string,omitempty"`
DeletedAt   time.Time `gorm:"type:timestamp" json:"deleted_at,string,omitempty"`

And Still Not Works, any solutions?

I expect the api work with no errors


Solution

  • When using gorm, you need to embed a gorm.Model struct, which includes fields ID, CreatedAt, UpdatedAt, DeletedAt.

    Reference

    // gorm.Model definition
    type Model struct {
      ID        uint           `gorm:"primaryKey"`
      CreatedAt time.Time
      UpdatedAt time.Time
      DeletedAt gorm.DeletedAt `gorm:"index"`
    }
    

    Not familiar with echo but read below to understand how you use gorm.

    In your case you can try doing the following:

    package schema
    
    type Quote struct {
        gorm.Model
        Title       string `json:"title"`
        Description string `json:"description"`
    }
    

    Then to get all the quotes:

    func GetAll() (Response, error) {
        var quotes []schema.Quote // slice
        ctx := db.Init()
        // Assuming
        // ctx, err := gorm.Open(....)
    
        // https://gorm.io/docs/query.html
        result := db.Find(&quotes)
        if result.Error != nil {
            return Response{
                Status: http.StatusInternalServerError,
                Message: "Query failed",
            },result.Error
        }
        if result.RowsAffected == 0 {
            return Response{
                Status: http.StatusNotFound,
                Message: "No records found",
            },nil
        }
        
        return Response{
            Status: http.StatusOK,
            Message: "Success",
            Data: quotes,
        },nil
    }
    

    Keep in mind that the Data field has type interface{}, which means it can hold a value of any type. If the value wasn't a slice you would be using the & operator you take the address of the Quote value. A slice is already a pointer to underlying slice so need to use the & operator.

    If you want to access the slice of Quote values from the Data field, you will need to use a type assertion to convert the value from the interface{} type to the []Quote type. Here's an example of how you could do this:

    // Assume that response.Data holds a slice of Quote values
    quotes, ok := response.Data.([]Quote)
    if !ok {
        // Handle the case where response.Data is not a slice of Quote
    }
    
    

    Warning: Since you are returning a slice, then any changes to the returned slice will be modifying the initial slice too. If you wanted to avoid this then copy the slice values to a new slice:

    quotesCopy = make([]schema.Quote, len(quotes))
    copy(quotesCopy, quotes)