SoFunction
Updated on 2025-03-05

An example explanation of Golang JSON's advanced usage

Pain points

json is one of the most commonly used data transmission formats at present. It is plain text, easy to use, easy to read, and is widely used during communication.

Have you ever encountered a dilemma when you fill in a certain type in a field in json? (For example: you define a port field, but you don’t know whether to fill in 8080 or “8080”)

Have you ever encountered a json anti-parsing error caused by mismatch in the type of fields? For example:

json: cannot unmarshal number into Go struct field of type string

Do you have the requirement that a certain json field is compatible with 2 or more data structures?

Do you want to make the program more elegant and adaptable without getting headaches with these small details?

If you have or you want, you can check out this article.

Reproduce the problem

We gave the user a json as follows:

{
 "name":"yulibaozi",
 "port":8080
}

However, the business party mistakenly filled in "8080", and as a result, our program counter-parsing error reported, resulting in business failure.

json: cannot unmarshal number into Go struct field of type string

Maybe you think this is a business party problem, but I think we can solve this problem more elegantly.

How to solve the problem

We first define a structure

type Host struct {
 Name string `json:"name"`
 Port Port `json:"port"`
}

If you are careful, you will find that Port is neither an int nor a string type, but a Port type, and the Port type is:

type Type int

const (
 Int Type = iota
 String
)

type Port struct {
 Type Type
 IntVal int
 StrVal string
}

In the Port structure, we found Type type, and Type type includes two types: int and string. Next is very important, we need to implement the following two interfaces.

 interface
 interface

The implementation code is as follows:

type Port struct {
 Type Type
 IntVal int
 StrVal string
}

// Implement the interfacefunc (port *Port) UnmarshalJSON(value []byte) error {
 if value[0] == '"' {
   = String
  return (value, &)
 }
  = Int
 return (value, &)
}

// Implement the interfacefunc (port Port) MarshalJSON() ([]byte, error) {
 switch  {
 case Int:
  return ()
 case String:
  return ()
 default:
  return []byte{}, ("impossible ")
 }
}

Next test:

Test anti-parsing

Test anti-parsing int

Give json data:

{"name":"yulibaozi","port":8090}

The structure data obtained by inverse parsing is as follows:

&{Name:yulibaozi Port:{Type:0 IntVal:8090 StrVal:}}

Test the anti-parsing string:

Give json data:

{"name":"yulibaozi","port":"8090"}

The structure data obtained by inverse parsing is as follows:

&{Name:yulibaozi Port:{Type:1 IntVal:0 StrVal:8090}}

Test encoding json

The structure of the test code int is as follows:

host := &Host{
   Name: "yulibaozi",
   Port: Port{
     Type:  Int,
     IntVal: 8080,
   },
 }

The encoded json is as follows:

{"name":"yulibaozi","port":8080}

The structure of the test encoding string is as follows:

host := &Host{
   Name: "yulibaozi",
   Port: Port{
     Type:  String,
     StrVal: "8080",
   },
 }

The encoded json data is as follows:

{"name":"yulibaozi","port":"8080"}

In the decoding test, you will find that when the type of json is filled in is different, it will be encoded into the corresponding fields in the structure.

In the encoding test, the specific encoding data is determined by Type.

Summarize

In fact, this article just shares the tips used in json. It breaks the impression that when using json, it needs a dull data structure, and turns to a changeable and flexible style. In fact, the core of these tips is to implement the two structures of Unmarshaller and Marshaller. Their implementation is the key to this sharing. Of course, you can implement as mentioned at the beginning, a certain field of json is compatible with 2 or more structures. Of course, you can also toss yaml, toml, etc. and you will get the answer you want.

Okay, the above is the entire content of this article. I hope that the content of this article has a certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support.