英文:
How to use `omitempty` with protobuf Timestamp in Golang
问题
我在我的结构体上有一个可选字段叫做ExpireTime
。它的类型是time.Time
,并且有一个json:"expire_time,omitempty"
的标签,表示当它为空时不发送该字段。这部分工作得非常好。
当我想通过GRPC使用同样的字段时,将其转换为protobuf时间戳格式时遇到了问题。
type Timestamp struct {
// 表示自Unix纪元以来的UTC时间的秒数
// 1970-01-01T00:00:00Z。必须在0001-01-01T00:00:00Z到
// 9999-12-31T23:59:59Z之间(包括边界)。
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
// 非负的纳秒分辨率的秒的小数部分。具有负秒值的小数部分仍然必须具有非负的纳秒值,
// 以便按时间向前计数。必须在0到999,999,999之间(包括边界)。
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
// 包含已过滤或未导出的字段
}
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`
问题在于一个空的time.Time{}
对象将被转换为一个负的seconds
值,对应于0001-01-01T00:00:00Z。在这种情况下,omitEmpty
标志将不会被应用,因为该值并没有被置零。我应该怎么做才能在字段实际为空时省略它呢?谢谢!
英文:
I have an optional field on my struct called ExpireTime
. It has a time.Time
type and a json:"expire_time,omitempty"
tag to not send it, when it is empty. This part works perfectly fine.
When I want to use the same field via GRPC, I run into an issue when converting it to the protobuf timestamp format.
type Timestamp struct {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
// contains filtered or unexported fields
}
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`
The issue is that an empty time.Time{}
object will be converted to a negative seconds
value corresponding to 0001-01-01T00:00:00Z. Having the omitEmpty
flag will not be applied in this case as the value is not zeroed out. What could I do to omit this field, when it is actually empty? Thanks!
答案1
得分: 2
根据你的要求,以下是翻译好的内容:
正如你所说,time.Time{}
转换为 0001-01-01T00:00:00Z
;这是按预期工作的。请注意,在相反的方向转换时也需要小心(零值的 TimeStamp
将变为 1970-01-01T00:00:00Z
)。
然而,通常 Timestamp
将作为消息的一部分,例如:
message MyMessage{
google.protobuf.Timestamp comm_time = 1;
}
通过 protoc
运行这段代码将得到类似以下的结果:
type MyMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
CommTime *timestamppb.Timestamp `protobuf:"bytes, 1,opt,name=comm_time,json=commTime,proto3" json:"comm_time,omitempty"`
}
这意味着你可以通过 CommTime=nil
来实现你想要的结果,例如:
sourceTime := time.Time{} // 你想要编码的时间
var commTime *timestamp.Timestamp
if !sourceTime.IsZero() {
commTime = timestamppb.New(sourceTime)
}
msg := MyMessage{
CommTime: commTime,
}
英文:
As you say time.Time{}
converts to 0001-01-01T00:00:00Z
; this is working as intended. Note that you also need to be careful converting in the opposite direction (a zero TimeStamp
will become 1970-01-01T00:00:00Z
).
However generally the Timestamp
will be part of a message, for example:
message MyMessage{
google.protobuf.Timestamp comm_time = 1;
}
Running this through protoc
will result in something like:
type MyMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
CommTime *timestamppb.Timestamp `protobuf:"bytes, 1,opt,name=comm_time,json=commTime,proto3" json:"comm_time,omitempty"`
}
This means you should be able to achieve the result you are looking for with CommTime=nil
; e.g.
sourceTime := time.Time{} // Whatever time you want to encode
var commTime *timestamp.Timestamp
if !sourceTime.IsZero() {
commTime = timestamppb.New(sourceTime)
}
msg := MyMessage{
CommTime: commTime,
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论