Tips for using JSON in Golang

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Sometimes the upstream field is a string type, but we want to use it as a number. Originally with one json:",string" can support, if do not know Golang these tips, will be a lot of trouble.

Reference article: http://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/

Temporarily ignores struct fields

type User struct {    Email    string `json:"email"`    Password string `json:"password"`    // many more fields…}

Temporarily Ignore password field

json.Marshal(struct {    *User    Password bool `json:"password,omitempty"`}{    User: user,})

Temporarily add extra fields

type User struct {    Email    string `json:"email"`    Password string `json:"password"`    // many more fields…}

Temporarily ignores the password field and adds a token field

json.Marshal(struct {    *User    Token    string `json:"token"`    Password bool `json:"password,omitempty"`}{    User: user,    Token: token,})

Temporary bonding of two structs

type BlogPost struct {    URL   string `json:"url"`    Title string `json:"title"`}type Analytics struct {    Visitors  int `json:"visitors"`    PageViews int `json:"page_views"`}json.Marshal(struct{    *BlogPost    *Analytics}{post, analytics})

A JSON cut into two structs

json.Unmarshal([]byte(`{  "url": "attila@attilaolah.eu",  "title": "Attila's Blog",  "visitors": 6,  "page_views": 14}`), &struct {  *BlogPost  *Analytics}{&post, &analytics})

field for temporarily renaming a struct

type CacheItem struct {    Key    string `json:"key"`    MaxAge int    `json:"cacheAge"`    Value  Value  `json:"cacheValue"`}json.Marshal(struct{    *CacheItem    // Omit bad keys    OmitMaxAge omit `json:"cacheAge,omitempty"`    OmitValue  omit `json:"cacheValue,omitempty"`    // Add nice keys    MaxAge int    `json:"max_age"`    Value  *Value `json:"value"`}{    CacheItem: item,    // Set the int by value:    MaxAge: item.MaxAge,    // Set the nested struct by reference, avoid making a copy:    Value: &item.Value,})

Passing numbers with a string

type TestObject struct {    Field1 int    `json:",string"`}

This corresponding JSON is{"Field1": "100"}

If JSON is {"Field1": 100} the error will be

Tolerate string and digital cross-transfer

If you are using Jsoniter, you can start the Blur mode to support the JSON that PHP passes over.

import "github.com/json-iterator/go/extra"extra.RegisterFuzzyDecoders()

This allows you to handle problems with strings and numbers that are not the same type. Like what

var val stringjsoniter.UnmarshalFromString(`100`, &val)

Another example

var val float32jsoniter.UnmarshalFromString(`"1.23"`, &val)

Tolerate empty arrays as objects

Another frustrating part of PHP is that if the PHP array is empty, the serialization is [] . But when it's not empty, it's serialized out {"key":"value"} . We need to treat it as a [] {} deal.

If you are using Jsoniter, you can start the Blur mode to support the JSON that PHP passes over.

import "github.com/json-iterator/go/extra"extra.RegisterFuzzyDecoders()

So that we can support the

var val map[string]interface{}jsoniter.UnmarshalFromString(`[]`, &val)

Support Time.time with Marshaljson

Golang will default to time. Time is serialized in string mode. If we want to represent time in other ways. Time, you need to customize the type and define Marshaljson.

type timeImplementedMarshaler time.Timefunc (obj timeImplementedMarshaler) MarshalJSON() ([]byte, error) {    seconds := time.Time(obj).Unix()    return []byte(strconv.FormatInt(seconds, 10)), nil}

Marshaljson is called when serializing

type TestObject struct {    Field timeImplementedMarshaler}should := require.New(t)val := timeImplementedMarshaler(time.Unix(123, 0))obj := TestObject{val}bytes, err := jsoniter.Marshal(obj)should.Nil(err)should.Equal(`{"Field":123}`, string(bytes))

Support Time.time with Registertypeencoder

Jsoniter can customize the JSON codec for a type that is not your definition. For example, time. Time can be serialized with the epoch Int64

import "github.com/json-iterator/go/extra"extra.RegisterTimeAsInt64Codec(time.Microsecond)output, err := jsoniter.Marshal(time.Unix(1, 1002))should.Equal("1000001", string(output))

If you want to customize, see RegisterTimeAsInt64Codec the implementation code

Use Marshaltext to support a map with non-string as key

Although the JSON standard supports only string as a key map. But Golang through the Marshaltext () interface, making other types available as a key to the map. For example

f, _, _ := big.ParseFloat("1", 10, 64, big.ToZero)val := map[*big.Float]string{f: "2"}str, err := MarshalToString(val)should.Equal(`{"1":"2"}`, str)

big.Floatthe Marshaltext () is realized.

Use JSON. Rawmessage

If some JSON documents do not have a standard format, we can save the original text information with a string.

type TestObject struct {    Field1 string    Field2 json.RawMessage}var data TestObjectjson.Unmarshal([]byte(`{"field1": "hello", "field2": [1,2,3]}`), &data)should.Equal(` [1,2,3]`, string(data.Field2))

Use JSON. Number

By default, if the interface{} corresponds to a number, the case will be float64 type. If you enter a larger number, this representation can be detrimental to accuracy. So you can UseNumber() enable json.Number to represent numbers in strings.

decoder1 := json.NewDecoder(bytes.NewBufferString(`123`))decoder1.UseNumber()var obj1 interface{}decoder1.Decode(&obj1)should.Equal(json.Number("123"), obj1)

Jsoniter supports this usage of the standard library. At the same time, the extended behavior allows Unmarshal to support Usenumber.

json := Config{UseNumber:true}.Froze()var obj interface{}json.UnmarshalFromString("123", &obj)should.Equal(json.Number("123"), obj)

Change the naming style of a field uniformly

Often field names in JSON are not the same as field names in Go. We can use field tag to modify it.

output, err := jsoniter.Marshal(struct {    UserName      string `json:"user_name"`    FirstLanguage string `json:"first_language"`}{    UserName:      "taowen",    FirstLanguage: "Chinese",})should.Equal(`{"user_name":"taowen","first_language":"Chinese"}`, string(output))

But a field to set, too troublesome. If you use Jsoniter, we can set the naming style uniformly.

import "github.com/json-iterator/go/extra"extra.SetNamingStrategy(LowerCaseWithUnderscores)output, err := jsoniter.Marshal(struct {    UserName      string    FirstLanguage string}{    UserName:      "taowen",    FirstLanguage: "Chinese",})should.Nil(err)should.Equal(`{"user_name":"taowen","first_language":"Chinese"}`, string(output))

Use a private field

The standard library for Go supports only public field. Jsoniter additional support for the private field. Need to be used SupportPrivateFields() to turn on the switch.

import "github.com/json-iterator/go/extra"extra.SupportPrivateFields()type TestObject struct {    field1 string}obj := TestObject{}jsoniter.UnmarshalFromString(`{"field1":"Hello"}`, &obj)should.Equal("Hello", obj.field1)
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.