最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

1.Quiz

有如下一個例子:

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

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

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

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

3.Resolving

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

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

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

然后我們再看看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是實現(xiàn)了json.Marshaler接口的。然后觀察到它的實現(xiàn)是把時間按照RFC3339Nano格式字符串值返回為json序列化結(jié)果,這和我們實際上運行程序看到的結(jié)果是一致的。

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

type RecordBrief struct {
	time.Time
	ID int
}

為什么ID字段不見了?正是因為匿名字段的原因,Golang中的這種用法有點類似于繼承,所以RecordBrief類型也自動具有了time.Time的所有方法,當(dāng)然也包括了MarshalJSON,從而也就實現(xiàn)了json.Marshaler接口。如此一來,當(dāng)一個RecordBrief被Marshal的時候,它的序列化結(jié)果就被time.Time的序列化結(jié)果給覆蓋了。

Conclusion

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

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

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

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

type RecordBrief struct {
	Time time.Time
	ID int
}

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

type RecordBrief struct {
	time.Time
	ID int
}
func (r RecordBrief) MarshalJSON() ([]byte, error) {
	//非常簡單的一種方式就是創(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言命令行操作命令詳細介紹

    Go語言命令行操作命令詳細介紹

    這篇文章主要介紹了Go語言命令行操作命令詳細介紹,本文重點介紹了go build、go clean、go fmt、go get等命令,需要的朋友可以參考下
    2014-10-10
  • 基于go微服務(wù)效率工具goctl深度解析

    基于go微服務(wù)效率工具goctl深度解析

    這篇文章主要為大家介紹了基于go微服務(wù)效率工具goctl深度解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 利用Golang解析json數(shù)據(jù)的方法示例

    利用Golang解析json數(shù)據(jù)的方法示例

    Go提供了原生的JSON庫,并且與語言本身有效的集成在了一起。下面這篇文章將給大家介紹關(guān)于利用Golang解析json數(shù)據(jù)的方法,文中給出了詳細的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-07-07
  • go語言生成隨機數(shù)和隨機字符串的實現(xiàn)方法

    go語言生成隨機數(shù)和隨機字符串的實現(xiàn)方法

    隨機數(shù)在很多時候都可以用到,尤其是登錄時,本文就詳細的介紹一下go語言生成隨機數(shù)和隨機字符串的實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下
    2021-12-12
  • golang文件服務(wù)器的兩種方式(可以訪問任何目錄)

    golang文件服務(wù)器的兩種方式(可以訪問任何目錄)

    這篇文章主要介紹了golang文件服務(wù)器的兩種方式,可以訪問任何目錄,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • 詳解如何保留Go程序崩潰現(xiàn)場

    詳解如何保留Go程序崩潰現(xiàn)場

    這篇文章主要為大家介紹了如何保留Go程序崩潰現(xiàn)場示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • GoFrame框架garray并發(fā)安全數(shù)組使用開箱體驗

    GoFrame框架garray并發(fā)安全數(shù)組使用開箱體驗

    這篇文章主要介紹了GoFrame框架garray并發(fā)安全數(shù)組使用開箱體驗,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Golang中調(diào)用deepseekr1的教程詳解

    Golang中調(diào)用deepseekr1的教程詳解

    這篇文章主要為大家詳細介紹了Golang中調(diào)用deepseekr1的相關(guān)教程,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解下
    2025-02-02
  • GO語言不固定參數(shù)函數(shù)與匿名函數(shù)的使用

    GO語言不固定參數(shù)函數(shù)與匿名函數(shù)的使用

    本文主要介紹了GO語言不固定參數(shù)函數(shù)與匿名函數(shù)的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 利用Go語言開發(fā)文件操作工具輕松處理所有文件

    利用Go語言開發(fā)文件操作工具輕松處理所有文件

    在后端開發(fā)中,文件操作是一個非常常見但又容易出錯的場景,本文小編要向大家介紹一個強大的 Go 語言文件操作工具庫,它能幫你輕松處理各種文件操作場景
    2025-03-03

最新評論

枝江市| 廊坊市| 郴州市| 平阳县| 察雅县| 伊川县| 孟津县| 丹江口市| 疏附县| 逊克县| 资溪县| 宁德市| 寻乌县| 肇源县| 达拉特旗| 宁夏| 上犹县| 聊城市| 容城县| 类乌齐县| 康保县| 富宁县| 黔江区| 潜江市| 阿城市| 霍林郭勒市| 长沙县| 福海县| 博湖县| 柘城县| 正定县| 胶州市| 盈江县| 黄山市| 旺苍县| 红桥区| 金门县| 永川市| 大荔县| 福鼎市| 泸西县|