Today I will talk about the three most common problems and solutions I encountered when I JSON encoding data in Go. Let’s see if I have scratched a lot of hair for these problems.
Custom JSON key name
I hesitated to add this question to the article because basically everyone knows it, but I still put it in the same question.Go
The classmates are more friendly.
Let’s start with the most common problem. First, when encoding data into JSON format in Go programs, we usually define the structure type first and store the data in the structure variable.
type Address struct { Type string City string Country string } type CreditCard struct { FirstName string LastName string Addresses []*Address Remark string } home := &Address{"private", "Aartselaar", "Belgium"} office := &Address{"work", "Boom", "Belgium"} card := VCard{"Jan", "Kersschot", []*Address{home, office}, "none"} js, err := (card) ("JSON format: %s", js)
Only the exported struct members are encoded, which is why we choose field names that start with capital letters. When encoding, the name of the structure field is used by default as the JSON object.key
, but generally JSON is forHTTP interface
Return data for use, in the interface specification, we generally require return data.snake case
Style field name. The solution to this problem is to customize the corresponding one in the structure field label when the structure is declared.JSON key
So we can change the structure declaration to the following:
type Address struct { Type string `json:"type"` City string `json:"city"` Country string `json:"country"` }
Ignore the specified fields when encoding JSON
Not all data we expect to encodeJSON
exposed to external interfaces, so for some sensitive fields we often want to use them from the encodedJSON
Ignore the data. So the above also said that only the exported structure members will be encoded. Some students will ask me if I can't use lowercase field names directly? However, unexported fields can only be accessed within the package. Such things that carry internal sensitive data are often the basic data of the application and are provided by the public package of the project. So how can we maintain the exportability of fields and make them available inJSON
Is it ignored in the data? Or use the structure tag for annotation, such as the structure defined below, which can use the ID cardIdCard
The fields are inJSON
Remove from the data:
type User struct { Name string `json:"name"` Age Int `json:"int"` IdCard string `json:"-"` }
The encoding/json source code and documentation list descriptions of the JSON encoding behavior that controls data through structure field labels:
// Field is ignored by this package. Field int `json:"-"` // Field appears in JSON as key "myName". Field int `json:"myName"` // Field appears in JSON as key "myName" and // the field is omitted from the object if its value is empty, // as defined above. Field int `json:"myName,omitempty"` // Field appears in JSON as key "Field" (the default), but // the field is skipped if empty. // Note the leading comma. Field int `json:",omitempty"`
omitempty This is when the data of the field is empty, this field is omitted in JSON. In order to save data space, the Protobuf compiler generates omitempty in each field tag. However, this is not commonly used in API development because the fields are not fixed and are not friendly to the front-end.
If you don’t know about Protobuf, you can read the article I wrote before, “Protobuf Language Guide 》。
There is a situation where no omitempty is added to the json annotation of the structure field label, that is, fields with data type slices will be encoded as null by JSON instead of [] when the data is empty. This front-end often asks me if I can not return null when there is no data, and I have to write an extra judgment each time. My words cannot be said, but in fact, the standardization is that I should return the knowledge []. I have not found a solution myself. As a person who has obsessive-compulsive disorder in writing code, I still want to figure out this question. Fortunately, one day I saw an answer on * and found out that it was caused by coding negligence.
Solve empty slices are encoded into null in JSON
Because the zero value of the slice is nil , there is no address pointing to memory, when var f []int is defined in this form to initialize slice, encode it as null in JSON. If you want to encode the empty slice as [] in JSON, you need to use make to initialize slice to allocate the memory address to it:
Run the following example to see the difference between two points:
package main import ( "encoding/json" "fmt" ) type Person struct { Friends []string } func main() { var f1 []string f2 := make([]string, 0) json1, _ := (Person{f1}) json2, _ := (Person{f2}) ("%s\n", json1) ("%s\n", json2) }
Output:
{"Friends":null } {"Friends":[] }
In fact, the reason for this problem is Go's append function (blaming the blame). We all know that if the value of reference type is not initialized after the definition of variables is nil, it cannot be used directly without the address pointing to memory. However, when append the slice, the append function will determine whether the slice has been initialized. If not, it will help it initialize and allocate the underlying array. My habit is to declare the slice first, and then append elements to the slice in the loop code below. However, if the loop is not executed, for example, if you do not find data from the database, it will cause the corresponding slice field to return nil when there is no data and then encoded into null by JSON. So this is a Tip summary from experience. Everyone must pay attention to when writing code.
These are the three problems and corresponding solutions I encountered when encoding data into JSON format during development. Adding to the previous article parsing JSON, the two articles can almost summarize various issues about the use of encoding/json library in daily development.
Summarize
The above is how to control the behavior of Go encoding JSON data that the editor introduced to you. I hope it will be helpful to you!