Golang中如何自定义时间类型进行xml、json的序列化/反序列化
在日常开发工作中,我们进行会遇到将 struct 序列化 json字符串以及将 json字符串 反序列化为 struct 的场景,大家也对此十分熟悉。
最近工作中,遇到了需要将 struct 序列化 xml字符串以及将 xml字符串 反序列化为 struct 的场景,对于普通类型的字段,比如int、string 等类型,直接使用并没有啥问题。
当遇到 时间类型 时,序列化和反序列化并不是自己想要的格式,这个时候就需要我们自定义时间类型的序列化/反序列化方式。
对于json序列化时间类型,大家可能已经比较熟悉了,一般是自定义一个时间类型或者为struct自定义MarshalJSON()([]byte, error)和UnmarshalJSON(b []byte) error方法,这样就可以实现将时间格式化为我们想要的格式了。
其实对于xml来说也是一样的,方式也是上面两种,这里就介绍下自定义时间类型,来实现xml的序列化/反序列化。
代码如下:
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"strings"
"time"
)
const timeLayout = "2006-01-02T15:04:05.000+08:00"
var location *time.Location
func init() {
location, _ = time.LoadLocation("Asia/Shanghai")
}
// XSDDateTime is a type for representing xsd:datetime in Golang
type XSDDateTime struct {
innerTime time.Time
}
func CreateXSDDateTime(dt time.Time) XSDDateTime {
return XSDDateTime{
innerTime: dt,
}
}
func (xdt XSDDateTime) String() string {
return xdt.innerTime.Format(timeLayout)
}
// ToGoTime converts the time to time.Time by checking if a TZ is specified.
// If there is a TZ, that TZ is used, otherwise local TZ is used
func (xdt *XSDDateTime) ToGoTime() time.Time {
return time.Date(xdt.innerTime.Year(), xdt.innerTime.Month(), xdt.innerTime.Day(),
xdt.innerTime.Hour(), xdt.innerTime.Minute(), xdt.innerTime.Second(),
xdt.innerTime.Nanosecond(), location)
}
func (xdt XSDDateTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
value := xdt.innerTime.Format(timeLayout)
attr := xml.Attr{Name: name, Value: value}
return attr, nil
}
func (xdt *XSDDateTime) UnmarshalXMLAttr(attr xml.Attr) error {
value := attr.Value
t, err := time.Parse(timeLayout, value)
if err != nil {
return err
}
xdt.innerTime = t
return nil
}
func (xdt XSDDateTime) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
formatted := xdt.innerTime.Format(timeLayout)
return e.EncodeElement(formatted, start)
}
func (xdt *XSDDateTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var value string
if err := d.DecodeElement(&value, &start); err != nil {
return err
}
parsedTime, err := time.Parse(timeLayout, value)
if err != nil {
return err
}
xdt.innerTime = parsedTime
return nil
}
func (xdt XSDDateTime) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, xdt.innerTime.Format(timeLayout))), nil
}
func (xdt *XSDDateTime) UnmarshalJSON(data []byte) error {
var dt time.Time
if err := json.Unmarshal(data, &dt); err != nil {
return err
}
xdt.innerTime = dt
return nil
}
type Test struct {
TD XSDDateTime `xml:"TD,attr"`
TD1 *XSDDateTime `xml:"TD1,attr,omitempty"`
T XSDDateTime `xml:"T"`
T1 *XSDDateTime `xml:"T1,omitempty"`
}
func main() {
// 创建一个 soap.XSDDateTime 类型的实例
xsdDateTime := CreateXSDDateTime(time.Now())
fmt.Println("now -->", time.Now())
t := Test{
TD: xsdDateTime,
T: xsdDateTime,
}
// 使用 xml.Marshal 将 soap.XSDDateTime 编组为 XML 数据
xmlData, err := xml.MarshalIndent(t, "", " ")
if err != nil {
fmt.Println("Error marshaling:", err)
return
}
// 输出编组后的 XML 数据
fmt.Println(string(xmlData))
fmt.Println(strings.Repeat("-", 10))
//tt := `<Test TD="2023-11-24T10:24:27.129+08:00">
//<T>2023-11-24T18:22:27.129+08:00</T>
//</Test>
//`
tt := string(xmlData)
var dddd Test
err = xml.Unmarshal([]byte(tt), &dddd)
fmt.Println(err)
fmt.Printf("Test --> %+v\n", dddd)
fmt.Printf("%v\n", dddd.T.ToGoTime())
fmt.Printf("%v\n", dddd.T.ToGoTime().Format(timeLayout))
}
执行结果:
now --> 2023-11-30 11:00:54.0918059 +0800 CST m=+0.003982301
<Test TD="2023-11-30T11:00:54.091+08:00">
<T>2023-11-30T11:00:54.091+08:00</T>
</Test>
----------
<nil>
t --> {TD:2023-11-30T11:00:54.091+08:00 TD1:<nil> T:2023-11-30T11:00:54.091+08:00 T1:<nil>}
2023-11-30 11:00:54.091 +0800 CST
2023-11-30T11:00:54.091+08:00
Golang中如何自定义时间类型进行xml、json的序列化/反序列化的更多相关文章
- Mybatis中使用自定义的类型处理器处理枚举enum类型
知识点:在使用Mybatis的框架中,使用自定义的类型处理器处理枚举enum类型 应用:利用枚举类,处理字段有限,可以用状态码,代替的字段,本实例,给员工状态字段设置了一个枚举类 状态码,直接赋值给对 ...
- Golang中的各种时间操作
Golang中的各种时间操作 需求 时间格式的转换比较麻烦,自己写了个工具,可以通过工具中的这些方法相互调用转成自己想要的格式,代码如下,后续有新的函数再添加 实现代码 package utils i ...
- MySQL 中常见的时间类型有三种 DATE, DATETIME 和 TIMESTAMP
MySQL 中常见的时间类型有三种 DATE, DATETIME 和 TIMESTAMP,其中 DATE 类型用于表示日期,但是不会包含时间,格式为 YYYY-MM-DD,而 DATETIME 和 T ...
- PHPExcel对于Excel中日期和时间类型的处理
PHPExcel是一款优秀的处理Excel文件读写的开源PHP Library,能够给我们提供强大的Excel读写能力,本文针对Excel处理过程中关于日期和时间类型的处理进行深入的讨论.PHPExc ...
- golang 中string和int类型相互转换
总结了golang中字符串和各种int类型之间的相互转换方式: string转成int: int, err := strconv.Atoi(string)string转成int64: int64, e ...
- MySQL 中的日期时间类型
日期时间类型中包含以下几种数据类型: DATE TIME DATETIME TIMESTAMP YEAR 各类型都有具体的取值范围,超出或非法的其他值时,MySQL 会回退到 0.TIMESTAMP ...
- MySQL中日期和时间类型
1 日期类型 MySql中关于日期的类型有Date/Datetime/Timestamp三种类型. 日期赋值时,允许"不严格"语法:任何标点符都可以用做日期部分或时间部分之间的间割 ...
- EF6中一个关于时间类型 datetime2 的坑
在一个访问下位机的程序中,返回的时间戳有时候因断线产生0001年01月01日的时间,而原先使用拼接SQL进行数据存储的操作时,这个问题是可以跳过的. 这次把拼接SQL的部分重新改为EF进行管理,这个坑 ...
- 在Spring MVC 中配置自定义的类型转换器
方法一: 实现spring mvc 自带的 Formatter 接口 1.创建一个类来实现Formatter接口 import org.springframework.format.Formatter ...
- Ext如何Gird中如何显示时间类型的列?
rt,后台bean中的字段属性是Date类型,前台的model中的字段属性也设置为date类型,但是还是显示不出来,如何解决呢? 直接代码: grid中的COLUMN: Model中的定义:
随机推荐
- nodejs中如何使用http创建一个服务
http模块是nodejs中非常重要的一部分,用于开启一个服务,我们可以用它自定义接口供客户端使用. 开启服务的方式也比较简单,几行代码就可以搞定 const http = require('ht ...
- markdown之mermaid
官方文档 01 简单的流程图 TD或TB:top to bottom,从上到下的流程图 LR:从左到右 其它:RL,BT flowchart LR; A([节点A的圆矩框]) --> |AB之间 ...
- [pandas]从多个文件中构建dataframe
按列从多个文件中构建 假设有两个csv文件,列不相同,需要整合为一个dataframe,使用glob模块: from glob import glob import pandas as pd # gl ...
- Java中锁的简单使用体验
锁是控制多个线程访问共享资源的一种同步机制. synchronized:可以将代码块或方法设置为同步. ReentrantLock:提供了比synchronized更广泛的锁操作函数. ReadWri ...
- [ABC146E] Rem of Sum is Num
2023-02-27 题目 题目传送门 翻译 翻译 难度&重要性(1~10):4 题目来源 AtCoder 题目算法 数学 解题思路 先对整个序列求前缀和 \(sum_k=\sum_{i=1} ...
- 微信小程序上传文件操作示范
社会实践心得体会格式要求 提交的心得体会应为word文档,且图文并茂,全文段前.段后0,1.5倍行距. 题目:自拟,方正小标宋简体,小二号,加粗,居中. 个人信息:题目下方,宋体,小四号,加粗,居中, ...
- 《Web安全基础》01. 基础知识
@ 目录 1:概念名词 1.1:域名 1.2:DNS 1.3:网站开发语言 1.4:后门 1.5:Web 1.6:Web 相关安全漏洞 2:数据包 2.1:HTTP 2.2:HTTPS 2.3:请求数 ...
- PowerDotNet平台化软件架构设计与实现系列(16):财务平台
不同行业基本都会有自己独特的业务,甚至同行的不同企业之间的业务逻辑也会相差千里,只有最大程度抽象出通用性.标准性和普适性的系统才能够成为平台系统,平台系统开发的成本和难度可想而知. 个人深度参与或独立 ...
- PXC集群脑裂导致节点是无法加入无主的集群
一套2节点的MySQL PXC集群,第1节点作为主用节点长时间的dml操作,导致大量的事务阻塞,出现异常,此时查看第2节点显示是primary状态,但无事务阻塞情况. 此时第1节点无法正常提供服务,于 ...
- Java-网络编程(TCP-UDP)
Java-网络编程(TCP-UDP) 网络基础 网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的.中间最主要 ...