This is a creation in Article, where the information may have evolved or changed.
Golang JSON Custom encode
Brief introduction
Golang Native provides very handy JSON processing, such as when a struct is converted to JSON, using ' JSON: ' name ' to set the JSON field directly on the member variable. In general, for the underlying type JSON. Marshal (object) satisfies the requirements, but for special cases it needs to be resolved by a custom JSON encode.
Special cases
Golang's official recommended set scheme is implemented via map.
custormSet := make(map [CustormStruct] bool)custormObj := custorm.NextObj()if _,ok := custormSet[custormObj];!ok{ custormSet[custormObj] = true}
This is the way to implement the functionality of a collection.
The problem is if a struct requires a member variable of a set type and needs to be converted to JSON. If you use JSON directly. Marshal (object) , the corresponding type becomes a map instead of the list of elements we need to not repeat.
Workaround
Case brief
Statistics all access to a local port IP, specific data collection methods are several, not the focus of this article is not introduced.
Realize
type ListenPort struct{Port intipSet [string] boolipList []*string}type NewPort(port int) ListenPort{ipSet := make([string] bool)ipList := []*string{}return ListenPort{port,ipSet,ipList,}}func (p *ListenPort)Add(ip string) {if _,ok:= p.ipSet[ip];!ok{p.ipSet[ip] = truep.ipList = append(p.ipList,&ip)}}//敲黑板!!!这是重点func (p ListenPort)MarshalJSON() ([]byte, error){return json.Marshal(&struct {Port int `json:"port"`Ips []*string `json:"ip"`}{Port: p.Port,Ips: p.ipList,})}
Test code
ipPort := NewPort(2333)ipPort.Add("127.0.0.1")ipPort.Add("116.211.174.177")ipPort.Add("106.39.167.11")ipPort.Add("220.181.57.2168")ipPort.Add("127.0.0.1")jsonbyte,err := json.Marshal(ipPort)if err != nil {fmt.Println(err)}fmt.Println(string(jsonbyte))
Description
The func (obj ObjectType) Marshaljson () ([]byte, Error) method should be an interface that implements JSON. Solve this problem by re-structuring a struct.
The code is my original, method is my Google's
Additional Instructions
The experiment shows that for reflect, a key list is obtained from the following code for map. The following code prints the same results as printing p.iplist
func (p *ListenPort)PrintlnIpList(){ fmt.Println(reflect.ValueOf(p.ipSet).MapKeys())}
After trying to find, directly using JSON to convert reflect. A variable of type value is given a {}
- Why choose to add a slice?
In fact, the new slice store is a string address and does not add much memory. for reflect. The value type does have a method to convert it again to a string type. It's just that every time you get a JSON conversion you need to traverse slice, which requires a tradeoff.
Ipset and IPList are private member variables, purely to see the business scenario needs
Summary
~blablabla~