欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang?中的json.Marshal問題總結(jié)(推薦)

 更新時(shí)間:2022年06月27日 15:04:02   作者:加拉薩假期  
這篇文章主要介紹了Golang中的json.Marshal問題總結(jié),本文通過一個(gè)例子給大家詳細(xì)講解,本次提出的問題中,我們不難注意到其中的time.Time是一個(gè)匿名(Anonymous)字段,而這個(gè)就是答案的由來(lái),需要的朋友可以參考下

1.Quiz

有如下一個(gè)例子:

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type RecordBrief struct {
	time.Time
	ID int
}

func main() {
	r := RecordBrief{
		Time: time.Now(),
		ID:   6,
	}
	m, _ := json.MarshalIndent(r, "", "\t")
	fmt.Println(string(m))
}

你期望的結(jié)果是像:

{
        "Time": "2022-06-25T10:49:39.597537249+08:00",
        "ID": 6
}

還是:

{
        "ID": 6
}

或者是別的?

2.Answer

其實(shí)如果你認(rèn)為的答案不是:

"2022-06-25T10:52:23.590933959+08:00"

也沒能想明白原因,可以繼續(xù)往下看看。

3.Resolving

誠(chéng)然,我們?cè)趯W(xué)習(xí)json的序列化和反序列化的時(shí)候,目的就是把一個(gè)Golang struct值序列化為對(duì)應(yīng)的json string罷了??赡芪覀冞€知道一些Marshal的規(guī)則,比如struct的字段需要定義為可導(dǎo)出的,比如還可通過定義對(duì)應(yīng)的json tag來(lái)修改struct field對(duì)應(yīng)的json字段名稱等。

但是對(duì)于json.Marshal函數(shù)的細(xì)節(jié)可能大家不會(huì)去太在意。本次提出的問題中,我們不難注意到其中的time.Time是一個(gè)匿名(Anonymous)字段,而這個(gè)就是答案的由來(lái)。我們先看看json.Marshal的注釋文檔中的一個(gè)解釋:

// ...
// Marshal traverses the value v recursively.
// If an encountered value implements the Marshaler interface
// and is not a nil pointer, Marshal calls its MarshalJSON method
// to produce JSON. If no MarshalJSON method is present but the
// value implements encoding.TextMarshaler instead, Marshal calls
// its MarshalText method and encodes the result as a JSON string.
// ...
func Marshal(v interface{}) ([]byte, error) {
	...
}

Marshal函數(shù)遞歸地遍歷傳入的序列化對(duì)象v(及其成員)。當(dāng)面對(duì)一個(gè)實(shí)現(xiàn)了json.Marshaler接口的對(duì)象(不能是一個(gè)空指針)時(shí),Marshal函數(shù)就會(huì)調(diào)用該對(duì)象的MarshalJSON方法來(lái)生成JSON內(nèi)容。如果沒有實(shí)現(xiàn)json.Marshaler,而是實(shí)現(xiàn)了encoding.TextMarshaler接口,那么就會(huì)調(diào)用它的MarshalText方法,然后把該方法返回的結(jié)果轉(zhuǎn)編為一個(gè)JSON字符串。

然后我們?cè)倏纯?code>time.Time:

type Time struct {
	...
}

// MarshalJSON implements the json.Marshaler interface.
// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
func (t Time) MarshalJSON() ([]byte, error) {
	if y := t.Year(); y < 0 || y >= 10000 {
		// RFC 3339 is clear that years are 4 digits exactly.
		// See golang.org/issue/4556#c15 for more discussion.
		return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
	}

	b := make([]byte, 0, len(RFC3339Nano)+2)
	b = append(b, '"')
	b = t.AppendFormat(b, RFC3339Nano)
	b = append(b, '"')
	return b, nil
}

所以time.Time是實(shí)現(xiàn)了json.Marshaler接口的。然后觀察到它的實(shí)現(xiàn)是把時(shí)間按照RFC3339Nano格式字符串值返回為json序列化結(jié)果,這和我們實(shí)際上運(yùn)行程序看到的結(jié)果是一致的。

那么再看看我們的type定義:

type RecordBrief struct {
	time.Time
	ID int
}

為什么ID字段不見了?正是因?yàn)槟涿侄蔚脑颍珿olang中的這種用法有點(diǎn)類似于繼承,所以RecordBrief類型也自動(dòng)具有了time.Time的所有方法,當(dāng)然也包括了MarshalJSON,從而也就實(shí)現(xiàn)了json.Marshaler接口。如此一來(lái),當(dāng)一個(gè)RecordBrief被Marshal的時(shí)候,它的序列化結(jié)果就被time.Time的序列化結(jié)果給覆蓋了。

Conclusion

如果你和我一樣,沒能一下知道原因,那多半是對(duì)一些常見的知識(shí)了解的深度和廣度不夠。我之前確實(shí)不知道time.Time居然也實(shí)現(xiàn)了json.Marshaler接口,也不清楚json.Marshal到底在做什么,所以不知道答案也就理所當(dāng)然了,后來(lái)經(jīng)過閱讀文檔注釋,才終于對(duì)該問題有了一些認(rèn)知(后續(xù)應(yīng)該總結(jié)一篇json.Marshal的源碼解析)。

至此,如果我們想要這種樣子的結(jié)果:

{
        "Time": "2022-06-25T10:49:39.597537249+08:00",
        "ID": 6
}

最簡(jiǎn)單的方式是修改struct,將time.Time作為一個(gè)非匿名的導(dǎo)出字段:

type RecordBrief struct {
	Time time.Time
	ID int
}

另一種方法是給我們的RecordBrief實(shí)現(xiàn)json.Marshaler接口:

type RecordBrief struct {
	time.Time
	ID int
}
func (r RecordBrief) MarshalJSON() ([]byte, error) {
	//非常簡(jiǎn)單的一種方式就是創(chuàng)建中間類型
	t := struct {
		Time time.Time
		ID   int
	}{
		r.Time,
		r.ID,
	}
	return json.Marshal(t)
}

到此這篇關(guān)于Golang 中的json.Marshal問題總結(jié)的文章就介紹到這了,更多相關(guān)Golang json.Marshal內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言中defer使用的陷阱小結(jié)

    Go語(yǔ)言中defer使用的陷阱小結(jié)

    本文主要介紹了Go語(yǔ)言中defer使用的陷阱小結(jié),分別是defer語(yǔ)句不可以在return語(yǔ)句之后,defer語(yǔ)句執(zhí)行的匿名函數(shù),匿名函數(shù)的參數(shù)會(huì)被預(yù)先處理,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • go語(yǔ)言中fallthrough的用法說(shuō)明

    go語(yǔ)言中fallthrough的用法說(shuō)明

    這篇文章主要介紹了go語(yǔ)言中fallthrough的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2021-05-05
  • 如何使用騰訊云go sdk 查詢對(duì)象存儲(chǔ)中最新文件

    如何使用騰訊云go sdk 查詢對(duì)象存儲(chǔ)中最新文件

    這篇文章主要介紹了使用騰訊云go sdk 查詢對(duì)象存儲(chǔ)中最新文件,這包括如何創(chuàng)建COS客戶端,如何逐頁(yè)檢索對(duì)象列表,并如何對(duì)結(jié)果排序以找到最后更新的對(duì)象,我們還展示了如何優(yōu)化用戶體驗(yàn),通過實(shí)時(shí)進(jìn)度更新和檢索多個(gè)文件來(lái)改進(jìn)程序,需要的朋友可以參考下
    2024-03-03
  • goland中文件頭自動(dòng)注釋的操作

    goland中文件頭自動(dòng)注釋的操作

    這篇文章主要介紹了goland中文件頭自動(dòng)注釋的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-12-12
  • golang中拿slice當(dāng)queue和拿list當(dāng)queue使用分析

    golang中拿slice當(dāng)queue和拿list當(dāng)queue使用分析

    這篇文章主要為大家介紹了golang?中拿slice當(dāng)queue和拿list當(dāng)queue使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • golang連接sqlx庫(kù)的操作使用指南

    golang連接sqlx庫(kù)的操作使用指南

    這篇文章主要為大家介紹了golang連接sqlx庫(kù)的操作使用指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • GoLang分布式鎖與snowflake雪花算法

    GoLang分布式鎖與snowflake雪花算法

    這篇文章主要介紹了GoLang分布式鎖與snowflake雪花算法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2022-12-12
  • Go指針的具體使用

    Go指針的具體使用

    本文主要介紹了Go指針的具體使用,包括使用指針、空指針、指針數(shù)組、指向指針的指針等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • GO語(yǔ)言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口

    GO語(yǔ)言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口

    這篇文章主要介紹了GO語(yǔ)言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • go語(yǔ)言求任意類型切片的長(zhǎng)度操作

    go語(yǔ)言求任意類型切片的長(zhǎng)度操作

    這篇文章主要介紹了go語(yǔ)言求任意類型切片的長(zhǎng)度操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2021-04-04

最新評(píng)論