golang

golang json gojay 라이브러리

kimbs0301 2024. 7. 5. 17:26

서버와 클라이언트 간 연동 시 구조체를 json으로 변환해서 할 경우 gojay 라이브러리의 Marshal 함수를 사용하면
json 생성을 golang에서 제공하는 라이브러리보다 좋은 성능을 낼 수 있다.
gojay를 사용할 경우 구조체 별로 MarshalJSONObject 함수 정의가 필요하다.

 

// Package main
package main // import "example.com/gojay/main"

import (
	"bytes"
	"encoding/json"
	"fmt"
	"testing"

	"github.com/francoispqt/gojay"
)

func Test1(t *testing.T) {
	a := Address{Text: "a", Post: 1, Enabled: true}

	c := &Car{Name: "a", Size: 1}

	p1 := Phone{Name: "a", Number: 1}
	p2 := Phone{Name: "2", Number: 1}

	var p PhoneSlice
	p = append(p, p1, p2)

	fm1 := FamilyMember{Name: "a", Age: 1, Phone: p}
	fm2 := FamilyMember{Name: "a", Age: 1, Address: Address{Text: "b", Post: 21, Enabled: true}}

	var fm FamilyMemberSlice
	fm = append(fm, fm1, fm2)

	v1 := Person{
		Name:         "a",
		Age:          1,
		BirthTime:    1,
		FriendName:   []string{"a", "b"},
		FriendAge:    []int{1, 2},
		Descr:        "123",
		Address:      a,
		Car:          c,
		FamilyMember: fm,
		Enabled:      true,
	}

	b, err := gojay.MarshalJSONObject(&v1)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
	}
	JsonPrettyDebugByBytes(b)

	v2 := Person{}
	err = gojay.UnmarshalJSONObject(b, &v2)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
	}
	bs, _ := json.Marshal(v2)
	fmt.Printf("json.Marshal %s\n", string(bs))
}

func JsonPrettyDebugByBytes(src []byte) {
	var buf bytes.Buffer
	json.Indent(&buf, src, "", "  ")
	fmt.Printf("%s\n", string(buf.Bytes()))
}

type Person struct {
	Name         string
	Age          int
	BirthTime    int64
	FriendName   []string
	FriendAge    []int
	Descr        interface{}
	Address      Address
	Car          *Car
	FamilyMember FamilyMemberSlice
	Enabled      bool
}

type Address struct {
	Text    string
	Post    int
	Enabled bool
}

type Car struct {
	Name string
	Size int
}

type FamilyMember struct {
	Name    string
	Age     int
	Phone   PhoneSlice
	Address Address
}

type FamilyMemberSlice []FamilyMember

type Phone struct {
	Name   string
	Number int
}

type PhoneSlice []Phone

 

/**
MarshalJSON ---
*/
func (p *Person) MarshalJSONObject(enc *gojay.Encoder) {
	enc.StringKey("Name", p.Name)
	enc.IntKey("Age", p.Age)
	enc.Int64Key("BirthTime", p.BirthTime)
	if len(p.FriendName) > 0 {
		enc.SliceStringKey("FriendName", p.FriendName)
	}
	if len(p.FriendAge) > 0 {
		enc.SliceIntKey("FriendAge", p.FriendAge)
	}
	enc.StringKey("Descr", p.Descr.(string))
	if p.Address.Text != "" {
		enc.ObjectKey("Address", &p.Address)
	}
	enc.ObjectKey("Car", p.Car)
	if len(p.FamilyMember) > 0 {
		enc.ArrayKey("FamilyMember", p.FamilyMember)
	}
	enc.BoolKey("Enabled", p.Enabled)
}

func (p *Person) IsNil() bool {
	return p == nil
}

func (a *Address) MarshalJSONObject(enc *gojay.Encoder) {
	enc.StringKey("Text", a.Text)
	enc.IntKey("Post", a.Post)
	enc.BoolKey("Enabled", a.Enabled)
}

func (a *Address) IsNil() bool {
	return a == nil
}

func (c *Car) MarshalJSONObject(enc *gojay.Encoder) {
	enc.StringKey("Name", c.Name)
	enc.IntKey("Size", c.Size)
}

func (c *Car) IsNil() bool {
	return c == nil
}

func (f *FamilyMember) MarshalJSONObject(enc *gojay.Encoder) {
	enc.StringKey("Name", f.Name)
	enc.IntKey("Age", f.Age)
	if len(f.Phone) > 0 {
		enc.ArrayKey("Phone", f.Phone)
	}
	if f.Address.Text != "" {
		enc.ObjectKey("Address", &f.Address)
	}
}

func (f *FamilyMember) IsNil() bool {
	return f == nil
}

func (p *Phone) MarshalJSONObject(enc *gojay.Encoder) {
	enc.StringKey("Name", p.Name)
	enc.IntKey("Number", p.Number)
}

func (p *Phone) IsNil() bool {
	return p == nil
}

func (f FamilyMemberSlice) MarshalJSONArray(enc *gojay.Encoder) {
	for _, v := range f {
		enc.Object(&v)
	}
}

func (f FamilyMemberSlice) IsNil() bool {
	return len(f) == 0
}

func (p PhoneSlice) MarshalJSONArray(enc *gojay.Encoder) {
	for _, v := range p {
		enc.Object(&v)
	}
}

func (p PhoneSlice) IsNil() bool {
	return len(p) == 0
}

/**
--- MarshalJSON
*/