经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JSON » 查看文章
Golang中如何自定义时间类型进行xml、json的序列化/反序列化
来源:cnblogs  作者:画个一样的我  时间:2023/12/1 9:37:01  对本文有异议

在日常开发工作中,我们进行会遇到将 struct 序列化 json字符串以及将 json字符串 反序列化为 struct 的场景,大家也对此十分熟悉。

最近工作中,遇到了需要将 struct 序列化 xml字符串以及将 xml字符串 反序列化为 struct 的场景,对于普通类型的字段,比如int、string 等类型,直接使用并没有啥问题。

当遇到 时间类型 时,序列化和反序列化并不是自己想要的格式,这个时候就需要我们自定义时间类型的序列化/反序列化方式。

对于json序列化时间类型,大家可能已经比较熟悉了,一般是自定义一个时间类型或者为struct自定义MarshalJSON()([]byte, error)UnmarshalJSON(b []byte) error方法,这样就可以实现将时间格式化为我们想要的格式了。

其实对于xml来说也是一样的,方式也是上面两种,这里就介绍下自定义时间类型,来实现xml的序列化/反序列化。

代码如下:

  1. package main
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "fmt"
  6. "strings"
  7. "time"
  8. )
  9. const timeLayout = "2006-01-02T15:04:05.000+08:00"
  10. var location *time.Location
  11. func init() {
  12. location, _ = time.LoadLocation("Asia/Shanghai")
  13. }
  14. // XSDDateTime is a type for representing xsd:datetime in Golang
  15. type XSDDateTime struct {
  16. innerTime time.Time
  17. }
  18. func CreateXSDDateTime(dt time.Time) XSDDateTime {
  19. return XSDDateTime{
  20. innerTime: dt,
  21. }
  22. }
  23. func (xdt XSDDateTime) String() string {
  24. return xdt.innerTime.Format(timeLayout)
  25. }
  26. // ToGoTime converts the time to time.Time by checking if a TZ is specified.
  27. // If there is a TZ, that TZ is used, otherwise local TZ is used
  28. func (xdt *XSDDateTime) ToGoTime() time.Time {
  29. return time.Date(xdt.innerTime.Year(), xdt.innerTime.Month(), xdt.innerTime.Day(),
  30. xdt.innerTime.Hour(), xdt.innerTime.Minute(), xdt.innerTime.Second(),
  31. xdt.innerTime.Nanosecond(), location)
  32. }
  33. func (xdt XSDDateTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
  34. value := xdt.innerTime.Format(timeLayout)
  35. attr := xml.Attr{Name: name, Value: value}
  36. return attr, nil
  37. }
  38. func (xdt *XSDDateTime) UnmarshalXMLAttr(attr xml.Attr) error {
  39. value := attr.Value
  40. t, err := time.Parse(timeLayout, value)
  41. if err != nil {
  42. return err
  43. }
  44. xdt.innerTime = t
  45. return nil
  46. }
  47. func (xdt XSDDateTime) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
  48. formatted := xdt.innerTime.Format(timeLayout)
  49. return e.EncodeElement(formatted, start)
  50. }
  51. func (xdt *XSDDateTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
  52. var value string
  53. if err := d.DecodeElement(&value, &start); err != nil {
  54. return err
  55. }
  56. parsedTime, err := time.Parse(timeLayout, value)
  57. if err != nil {
  58. return err
  59. }
  60. xdt.innerTime = parsedTime
  61. return nil
  62. }
  63. func (xdt XSDDateTime) MarshalJSON() ([]byte, error) {
  64. return []byte(fmt.Sprintf(`"%s"`, xdt.innerTime.Format(timeLayout))), nil
  65. }
  66. func (xdt *XSDDateTime) UnmarshalJSON(data []byte) error {
  67. var dt time.Time
  68. if err := json.Unmarshal(data, &dt); err != nil {
  69. return err
  70. }
  71. xdt.innerTime = dt
  72. return nil
  73. }
  74. type Test struct {
  75. TD XSDDateTime `xml:"TD,attr"`
  76. TD1 *XSDDateTime `xml:"TD1,attr,omitempty"`
  77. T XSDDateTime `xml:"T"`
  78. T1 *XSDDateTime `xml:"T1,omitempty"`
  79. }
  80. func main() {
  81. // 创建一个 soap.XSDDateTime 类型的实例
  82. xsdDateTime := CreateXSDDateTime(time.Now())
  83. fmt.Println("now -->", time.Now())
  84. t := Test{
  85. TD: xsdDateTime,
  86. T: xsdDateTime,
  87. }
  88. // 使用 xml.Marshal 将 soap.XSDDateTime 编组为 XML 数据
  89. xmlData, err := xml.MarshalIndent(t, "", " ")
  90. if err != nil {
  91. fmt.Println("Error marshaling:", err)
  92. return
  93. }
  94. // 输出编组后的 XML 数据
  95. fmt.Println(string(xmlData))
  96. fmt.Println(strings.Repeat("-", 10))
  97. //tt := `<Test TD="2023-11-24T10:24:27.129+08:00">
  98. //<T>2023-11-24T18:22:27.129+08:00</T>
  99. //</Test>
  100. //`
  101. tt := string(xmlData)
  102. var dddd Test
  103. err = xml.Unmarshal([]byte(tt), &dddd)
  104. fmt.Println(err)
  105. fmt.Printf("Test --> %+v\n", dddd)
  106. fmt.Printf("%v\n", dddd.T.ToGoTime())
  107. fmt.Printf("%v\n", dddd.T.ToGoTime().Format(timeLayout))
  108. }

执行结果:

  1. now --> 2023-11-30 11:00:54.0918059 +0800 CST m=+0.003982301
  2. <Test TD="2023-11-30T11:00:54.091+08:00">
  3. <T>2023-11-30T11:00:54.091+08:00</T>
  4. </Test>
  5. ----------
  6. <nil>
  7. t --> {TD:2023-11-30T11:00:54.091+08:00 TD1:<nil> T:2023-11-30T11:00:54.091+08:00 T1:<nil>}
  8. 2023-11-30 11:00:54.091 +0800 CST
  9. 2023-11-30T11:00:54.091+08:00

原文链接:https://www.cnblogs.com/huageyiyangdewo/p/17868923.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号