Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gtime 建议增加一个默认format和JSON序列化设置 #1560

Closed
locxiang opened this issue Jan 8, 2022 · 2 comments
Closed

gtime 建议增加一个默认format和JSON序列化设置 #1560

locxiang opened this issue Jan 8, 2022 · 2 comments
Labels
rejected The proposal or PR is not accepted, which might be conflicted with our design or plan.

Comments

@locxiang
Copy link

locxiang commented Jan 8, 2022

1. What version of Go and system type/arch are you using?

go 1.16.5, linux/amd64

2. What version of GoFrame are you using?

v2

3. Can this issue be re-produced with the latest release?

建议增加一个format设置的功能,有的场景json输出时间是需要时间戳的

比如:

gtime.SetDefaultFormat("YYYY/MM/DD")

gtime.SetMarshalJSON(func() ([]byte,error){
//TODO 自实现业务逻辑
})

gtime.SetUnmarshalJSON(func(b []byte) error{
//TODO 自实现业务逻辑
})

gtime.SetUnmarshalText(func(b []byte) error{
//TODO 自实现业务逻辑
})
@gqcn
Copy link
Member

gqcn commented Feb 15, 2022

@locxiang 这种全局设置不太合适,尤其是针对基础库。建议你可以自定义一个时间类型,然后自行实现MarshalJSON来实现自定义逻辑。

type MyTime gtime.Time
func(t MyTime)MarshalJSON() ([]byte,error) {
    // ...
}

@gqcn gqcn closed this as completed Feb 15, 2022
@gqcn gqcn added the rejected The proposal or PR is not accepted, which might be conflicted with our design or plan. label Feb 15, 2022
@jan-bar
Copy link

jan-bar commented Dec 1, 2023

最近我也有需求序列化gtime.Time时带上时区信息,和前端对接要求都是标准的UTC时间字符串。搜到这个issues,虽然已经被拒绝,但我还是想留下我的解决方案。使用下面的中间件替换 ghttp.MiddlewareHandlerResponse 这个自带的中间件。

我觉得当前项目应该支持让使用者指定哪些json解析器。gin就支持,https://github.com/gin-gonic/gin/blob/master/internal/json/jsoniter.go

package middleware

import (
	"net/http"
	"time"
	"unsafe"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/os/gtime"
	jsoniter "github.com/json-iterator/go"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary

func init() {
	jsoniter.RegisterTypeEncoder("*gtime.Time", &timeCodec{})
}

type timeCodec struct {
}

func (codec *timeCodec) IsEmpty(ptr unsafe.Pointer) bool {
	ts := *(**gtime.Time)(ptr)
	return ts == nil || ts.UnixNano() == 0
}

func (codec *timeCodec) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
	var s string
	if ts := *(**gtime.Time)(ptr); ts != nil {
		s = ts.Time.UTC().Format(time.RFC3339Nano)
	}
	stream.WriteString(s)
}

type DefaultHandlerResponse struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data"`
}

func HandlerResponse(r *ghttp.Request) {
	// 复制 ghttp.MiddlewareHandlerResponse 代码

	r.Middleware.Next()

	if r.Response.BufferLength() > 0 {
		return
	}

	var (
		msg  string
		err  = r.GetError()
		res  = r.GetHandlerResponse()
		code = gerror.Code(err)
	)
	if err != nil {
		if code == gcode.CodeNil {
			code = gcode.CodeInternalError
		}
		msg = err.Error()
	} else {
		if r.Response.Status > 0 && r.Response.Status != http.StatusOK {
			msg = http.StatusText(r.Response.Status)
			switch r.Response.Status {
			case http.StatusNotFound:
				code = gcode.CodeNotFound
			case http.StatusForbidden:
				code = gcode.CodeNotAuthorized
			default:
				code = gcode.CodeUnknown
			}
			err = gerror.NewCode(code, msg)
			r.SetError(err)
		} else {
			code = gcode.CodeOK
		}
	}

	r.Response.Header().Set("Content-Type", "application/json")

	content := DefaultHandlerResponse{
		Code:    code.Code(),
		Message: msg,
		Data:    res,
	}

	// 拦截某些json序列化,例如 gtime.Time 序列化为UTC时区字符串
	if b, err := json.Marshal(content); err != nil {
		panic(gerror.Wrap(err, `WriteJson failed`))
	} else {
		r.Response.Write(b)
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rejected The proposal or PR is not accepted, which might be conflicted with our design or plan.
Projects
None yet
Development

No branches or pull requests

3 participants