go json.Marshalグループ関数の説明
13505 ワード
go標準ライブラリ(ソースバージョンgo 1.9)は、メタデータをslice関数にグループ化し、jsonを呼び出す.Marshal()関数が完了しました.
実行結果:
なお、符号化プロセスではデフォルトでstructのフィールド名をJSONのオブジェクトとして使用し(reflect技術により)、導出されたフィールドのみが符号化されます.これも、大文字で始まるフィールドを使用する理由です.また、グループ化された後、sliceが「和」記号、stringが「」記号を加えた場合......この関数がどのように処理されているかを見てみましょう.
encodeStateのmarshalメソッドの呼び出しを続行
reflectValue関数
valueEncoderの生成
typeEncoder:キャッシュにこのタイプのencoder処理関数を探してみて、パフォーマンスを向上させ、見つからない場合は新規作成
新タイプEncoer(reflect.Type,bool)関数:この関数の役割は反射に基づいてタイプ関数を決定し、さらに符号化する
関数の一例としてintEncoder
package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
type Movie struct {
Title string
Year int `json:"released"`
Color bool `json:"color,omitempty"`
Actors []string
}
var movies = []Movie{
{Title: "Casablanca", Year: 1942, Color: false,
Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}},
{Title: "Cool Hand Luke", Year: 1967, Color: true,
Actors: []string{"Paul Newman"}},
{Title: "Bullitt", Year: 1968, Color: true,
Actors: []string{"Steve McQueen", "Jacqueline Bisset"}},
}
data, err := json.Marshal(movies)
if err != nil {
log.Fatalf("JSON marshaling failed: %s", err)
}
fmt.Printf("%s
", data)
}
実行結果:
[{"Title":"Casablanca","released":1942,"Actors":["Humphrey Bogart","Ingrid Bergman"]},{"Title":"Cool Hand Luke","released":1967,"color":true,"Actors":["Paul Newman"]},{"Title":"Bullitt","released":1968,"color":true,"Actors":["Steve McQueen","Jacqueline Bisset"]}]
なお、符号化プロセスではデフォルトでstructのフィールド名をJSONのオブジェクトとして使用し(reflect技術により)、導出されたフィールドのみが符号化されます.これも、大文字で始まるフィールドを使用する理由です.また、グループ化された後、sliceが「和」記号、stringが「」記号を加えた場合......この関数がどのように処理されているかを見てみましょう.
func Marshal(v interface{}) ([]byte, error) {
// v bytes.Buffer ( )
e := &encodeState{}
// marshal ,encOpts :
err := e.marshal(v, encOpts{escapeHTML: true})
if err != nil {
return nil, err
}
return e.Bytes(), nil
}
// : escapeHtml true, 、& , , Encoder : bf := bytes.NewBuffer([]byte{});jsonEncoder := json.NewEncoder(bf);jsonEncoder.SetEscapeHTML(false);jsonEncoder.Encode(interface{})
type encOpts struct {
// true:int float “” ; false
quoted bool
escapeHTML bool
}
// v bytes.Buffer
type encodeState struct {
bytes.Buffer // accumulated output
scratch [64]byte
}
encodeStateのmarshalメソッドの呼び出しを続行
func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
if s, ok := r.(string); ok {
panic(s)
}
err = r.(error)
}
}()
// relectValue
e.reflectValue(reflect.ValueOf(v), opts)
return nil
}
reflectValue関数
func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
// valueEncoder encoderFunc (e,v,opts)
valueEncoder(v)(e, v, opts)
}
valueEncoderの生成
func valueEncoder(v reflect.Value) encoderFunc {
// reflect.value
if !v.IsValid() {
return invalidValueEncoder
}
// typeEncoder
return typeEncoder(v.Type())
}
typeEncoder:キャッシュにこのタイプのencoder処理関数を探してみて、パフォーマンスを向上させ、見つからない場合は新規作成
func typeEncoder(t reflect.Type) encoderFunc {
//encoderCache sync.Map encoderFunc , ,
if fi, ok := encoderCache.Load(t); ok {
return fi.(encoderFunc)
}
var (
wg sync.WaitGroup
f encoderFunc
)
wg.Add(1)
fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
wg.Wait()
f(e, v, opts)
}))
if loaded {
return fi.(encoderFunc)
}
//Cache ,
f = newTypeEncoder(t, true)
wg.Done()
// encoderFunc type:encoderFunc map
encoderCache.Store(t, f)
return f
}
新タイプEncoer(reflect.Type,bool)関数:この関数の役割は反射に基づいてタイプ関数を決定し、さらに符号化する
func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
// MarshalJSON() ([]byte, error) ,
if t.Implements(marshalerType) {
return marshalerEncoder
}
if t.Kind() != reflect.Ptr && allowAddr {
if reflect.PtrTo(t).Implements(marshalerType) {
return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
}
}
// MarshalText() (text []byte, err error)
if t.Implements(textMarshalerType) {
return textMarshalerEncoder
}
if t.Kind() != reflect.Ptr && allowAddr {
if reflect.PtrTo(t).Implements(textMarshalerType) {
return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
}
}
switch t.Kind() {
case reflect.Bool:
return boolEncoder
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return intEncoder
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return uintEncoder
case reflect.Float32:
return float32Encoder
case reflect.Float64:
return float64Encoder
case reflect.String:
return stringEncoder
case reflect.Interface:
return interfaceEncoder
case reflect.Struct:
return newStructEncoder(t)
case reflect.Map:
return newMapEncoder(t)
case reflect.Slice:
return newSliceEncoder(t)
case reflect.Array:
return newArrayEncoder(t)
case reflect.Ptr:
return newPtrEncoder(t)
default:
return unsupportedTypeEncoder
}
}
関数の一例としてintEncoder
func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
// []byte
b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
if opts.quoted {
e.WriteByte('"')
}
// bytes.Buffer
e.Write(b)
if opts.quoted {
e.WriteByte('"')
}
}