Goのjson解析:MarshalとUnmarshal

3366 ワード

Json Marshal:データをjson文字列に符号化する
簡単な例を見てみましょう
type Stu struct {
    Name  string `json:"name"`
    Age   int
    HIgh  bool
    sex   string
    Class *Class `json:"class"`
}

type Class struct {
    Name  string
    Grade int
}

func main() {
    //         ,    json   
    stu := Stu{
        Name: "  ",
        Age:  18,
        HIgh: true,
        sex:  " ",
    }

    //    
    cla := new(Class)
    cla.Name = "1 "
    cla.Grade = 3
    stu.Class=cla

    //Marshal   err!=nil
    jsonStu, err := json.Marshal(stu)
    if err != nil {
        fmt.Println("  json     ")
    }

    //jsonStu []byte  ,   string      
    fmt.Println(string(jsonStu))
}

結果:
{"name":"  ","Age":18,"HIgh":true,"class":{"Name":"1 ","Grade":3}}

結果から、
  • は、エクスポート可能なメンバー(変数の頭文字が大文字)であれば、jsonに変換できます.メンバー変数sexはエクスポートできないため、jsonに変換できません.
  • 変数にjsonラベルが付けられている場合、Nameの隣のjson:"name"のように、変換されたjson keyはそのラベル「name」を使用し、そうでなければ変数名をkey、例えば「Age」、「HIgh」とします.
  • boolタイプもjsonのvalue値に直接変換できます.Channel,complexおよび関数はjson文字列を符号化できない.もちろん、ループのデータ構造もだめで、marshalがデッドサイクルに陥ることになります.
  • ポインタ変数は、符号化時にcla変数のような値に自動的に変換されます.(もちろん、ポインタを渡さず、Stu structのメンバーClassをClass structタイプに変えれば、効果もそっくりです.ただしポインタが速く、メモリスペースを節約できます.)
  • 最後に、jsonが文字列に符号化された後、純粋な文字列であることを強調した.

  • 上のメンバー変数はすべて既知のタイプであり、stringタイプのNameがstringタイプのデータを割り当てることができるなど、指定したタイプしか受信できません.しかし,汎用性のために,あるいはコードを簡潔にするために,種々のタイプのデータを受け入れ,json符号化を行うタイプが望ましい場合がある.これはinterface{}タイプを使用します.
    Json Unmarshal:json文字列を対応するデータ構造に復号
    上記の例を復号化します
    type StuRead struct {
        Name  interface{} `json:"name"`
        Age   interface{}
        HIgh  interface{}
        sex   interface{}
        Class interface{} `json:"class"`
        Test  interface{}
    }
    
    type Class struct {
        Name  string
        Grade int
    }
    
    func main() {
        //json    "  ,  \    ,      
        //json          ,  key        ,    sex  
        data:="{\"name\":\"  \",\"Age\":18,\"high\":true,\"sex\":\" \",\"CLASS\":{\"naME\":\"1 \",\"GradE\":3}}"
        str:=[]byte(data)
    
        //1.Unmarshal       json   ,        json       。
        //          ,           , stu     StuRead{}
        //2.    stu:=new(StuRead),   stu      
        stu:=StuRead{}
        err:=json.Unmarshal(str,&stu)
    
        //       , json       , " , } 。
        if err!=nil{
            fmt.Println(err)
        }
    
        fmt.Println(stu)
    }

    結果:
    {   18 true  map[naME:1  GradE:3] }

    まとめ:
  • json文字列解析では、解析後のデータを受信する「受信体」が必要であり、Unmarshalでは受信体がポインタを渡さなければならない.そうでなければ解析は誤りを報告しないが,データは受信体に付与できない.ここではStuRead{}受信を使用します.
  • 解析の場合、受信体は自己定義することができる.json列のkeyは、受信体で一致するアイテムを自動的に探して付与します.一致ルールは、(1)keyと同じjsonタグを検索し、検索するとそのタグに対応する変数(Nameなど)が割り当てられます.(2)jsonタグがない場合は,Ageのように変数名がkeyと同じ変数を上から順に検索する.あるいは変数名は大文字と小文字のkeyと同じ変数を無視します.HIgh、Classのように.最初のマッチングは値を割り当て、後でマッチングがあっても無視します.(この変数は、書き出し可能、すなわち頭文字大文字である必要があることを前提とします).
  • 導出不可能な変数は解析できない(例えばsex変数、json列にkeyがsexのk-vがあるが、解析後もその値はnil、すなわち空の値)
  • .
  • 受信体にjson列で一致しない項目が存在する場合、解析は自動的にその項目を無視し、その項目は元の値を保持する.変数Testのように、空の値nilを保持します. 

  • 変換元:https://cloud.tencent.com/developer/article/1515861