Home > Backend Development > Golang > How to differentiate between empty fields and unset fields when using JSON in Golang

How to differentiate between empty fields and unset fields when using JSON in Golang

藏色散人
Release: 2020-09-09 09:37:29
forward
2964 people have browsed it

The following column golang tutorial will introduce to you how to use JSON time to distinguish empty fields and unset fields in How to differentiate between empty fields and unset fields when using JSON in Golanglang. I hope it will be helpful to friends in need!

How to differentiate between empty fields and unset fields when using JSON in Golang

A few weeks ago, I was working on a How to differentiate between empty fields and unset fields when using JSON in Golanglang microservice and needed to add support for CURP operations using JSON data. Typically, I would create a struct for the entity. All fields and the 'omitempty' attribute are defined in the body, as shown below

type Article struct {
   Id   string      `json:"id"`
   Name string      `json:"name,omitempty"`
   Desc string      `json:"desc,omitempty"`
}
Copy after login

Problem

But this representation brings serious problems, especially for Update Or Edit operation.

For example, suppose the JSON data of the update request looks like this

{"id":"1234","name":"xyz","desc":""}
Copy after login

Note the empty desc field. Now let us take a look at the request data in What does it look like after unblocking in How to differentiate between empty fields and unset fields when using JSON in Golang

func Test_JSON1(t *testing.T) {         
   jsonData:=`{"id":"1234","name":"xyz","desc":""}`
   req:=Article{}
   _=json.Unmarshal([]byte(jsonData),&req)
   fmt.Printf("%+v",req)
}Output:
=== RUN   Test_JSON1
{Id:1234 Name:xyz Desc:}
Copy after login

The description here is an empty string. Obviously the client wants to set desc to an empty string, which is inferred by our program.

However, if the client does not wish to change the existing value of Desc, in which case it is incorrect to send a description string again, so the requested JSON data may look like this

{"id":"1234","name":"xyz"}

We unblock it into our structure

func Test_JSON2(t *testing.T) {         
   jsonData:=`{"id":"1234","name":"xyz"}`
   req:=Article{}
   _=json.Unmarshal([]byte(jsonData),&req)
   fmt.Printf("%+v",req)
}Output:
=== RUN   Test_JSON2
{Id:1234 Name:xyz Desc:}
Copy after login

Well, Desc will still be Obtained as an empty string, so how to distinguish between unset fields and empty fields

Short answer? Pointers

Solution

Subject to some Inspired by existing How to differentiate between empty fields and unset fields when using JSON in Golanglang libraries like go-github. We can change the struct fields to pointer types as shown below

type Article struct {
   Id    string      `json:"id"`
   Name *string      `json:"name,omitempty"`
   Desc *string      `json:"desc,omitempty"`
}
Copy after login

By doing this, we add additional status. If the field does not exist in the original JSON, the structure field will be empty (nil).

On the other hand, if the field does exist and is null, then the pointer is not null and the field contains a null value.

Note - I did not change the 'Id' field to a pointer type because It does not have an empty status, the id is required, similar to the id in the database.

Let’s try again.

func Test_JSON_Empty(t *testing.T) {
   jsonData := `{"id":"1234","name":"xyz","desc":""}`
   req := Article{}
   _ = json.Unmarshal([]byte(jsonData), &req)
   fmt.Printf("%+v\n", req)
   fmt.Printf("%s\n", *req.Name)
   fmt.Printf("%s\n", *req.Desc)
}
func Test_JSON_Nil(t *testing.T) {
   jsonData := `{"id":"1234","name":"xyz"}`
   req := Article{}
   _ = json.Unmarshal([]byte(jsonData), &req)
   fmt.Printf("%+v\n", req)
   fmt.Printf("%s\n", *req.Name)
}
Copy after login

Output

=== RUN   Test_JSON_Empty
{Id:1234 Name:0xc000088540 Desc:0xc000088550}
Name: xyz
Desc: 
--- PASS: Test_JSON_Empty (0.00s)=== RUN   Test_JSON_Nil
{Id:1234 Name:0xc00005c590 Desc:<nil>}
Name: xyz
--- PASS: Test_JSON_Nil (0.00s)
Copy after login

The first case , since desc is set to an empty string, we get a non-null pointer in Desc and contains the value of an empty string. In the second case, the field is not set, and we get a null character String pointer.

So we can distinguish two types of updates. This method not only applies to strings, but also to all other data types, including integers, nested structures, etc.

But there are also some problems with this approach.

Null safety: Non-pointer data types have inherent null safety. In How to differentiate between empty fields and unset fields when using JSON in Golanglang this means string or Integers can never be null. They always have a default value. But if pointers are defined, these data types default to null unless set manually. Therefore, attempts to access those pointers without verifying nullability data may cause the application to crash.

# 以下代码将崩溃, 因为 desc 为空
func Test_JSON_Nil(t *testing.T) {
   jsonData := `{"id":"1234","name":"xyz"}`
   req := Article{}
   _ = json.Unmarshal([]byte(jsonData), &req)
   fmt.Printf("%+v\n", req)
   fmt.Printf("%s\n", *req.Desc)
}
Copy after login

This problem can be easily solved by always checking for a null pointer, but your code may look verbose.

Yes Printability: As you may have noticed in the output of the pointer-based solution, the value of the pointer is not printed. Twenty prints the hexadecimal value of the pointer, which is of little use in the application . This can also be overcome by re-using the stringer interface.

func (a *Article) String() string {
   output:=fmt.Sprintf("Id: %s ",a.Id)
   if a.Name!=nil{
   output+=fmt.Sprintf("Name: &#39;%s&#39; ",*a.Name)
   }
   if u.Desc!=nil{
   output+=fmt.Sprintf("Desc: &#39;%s&#39; ",u.Desc)
   }
   return output
}
Copy after login

Appendix:

  • Another way to solve the above problem is to use a nullable A third-party library of types whose types can provide methods for checking whether they are empty without caring about pointers.
  • github.com/guregu/null
  • github.com/google/go-github

Original address: https://medium.com/@arpitkh96/differentiate-between-empty-and-not-set-fields-with-json-in-golang-957bb2c5c065

Translation address: https://learnku.com/go/t/49332

The above is the detailed content of How to differentiate between empty fields and unset fields when using JSON in Golang. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:learnku.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template