Golang serializes / deserializes an empty array differently from null

Is there a way to serialize an empty attribute of an array (not zero) of the structure and deserialize it back to an empty array (again not zero)?

Given that an empty array is actually a pointer to zero, is the noticeable initial difference between an empty array and a pointer to zero completely lost after serialization / deserialization?

The worst practical scenario is that when I show an empty array attribute to my REST client, like json "att": [], for the first time, and after the cache register restarts and restores it, the same attribute will be shown to my client as "att": zero, as a result of which the contract is violated and very confused.

To summarize : it is possible to show the addresses of Client 2 as an empty json array, after serialize / deserialize => https://play.golang.org/p/TVwvTWDyHZ

+6
source share
3 answers

I'm sure the easiest way to do this is to change your line

var cust1_recovered Customer 

to

 cust1_recovered := Customer{Addresses: []Address{}} 

If I am not reading your question correctly, I consider this to be your desired result:

 ORIGINAL Customer 2 { "Name": "Customer number 2", "Addresses": [] } RECOVERED Customer 2 { "Name": "Customer number 2", "Addresses": [] } 

Here is a playground to test: https://play.golang.org/p/T9K1VSTAM0

The limitation here, as pointed out by @mike, is that if Addresses really nil before encoding, once you decode, you will not get the json equivalent of null , but instead get an empty list.

+10
source

No, It is Immpossible. To see why, take a look at the Go spec. So that it produces two different results for empty vs. nil, any serialization method would have to determine the difference between the two. However, according to the Go specification,

Two types of array are identical if they have the same element types and the same array length.

Since none of them contain any elements and have the same type of element, the only difference may be in length, but it also states that

The length of the zero fragment, card or channel is 0

Thus, by comparison, it would be impossible to say. Of course, there are methods other than comparisons, so to really put a nail in the coffin, here is the part that shows that they have the same basic idea. The specification also ensures that

The type of the structure or array is 0 if it does not contain fields (or elements, respectively) whose size is greater than zero.

therefore, the actual distributed structure of a zero-length array must be zero. If it is zero, it cannot store information about whether it is empty or nil , therefore the object itself also cannot know. In short, there is no difference between a nil array and a zero-length array.

The "noticeable initial difference between an empty array and a pointer to zero" is not lost during serialization / deserialization, it is lost from the moment the initial assignment is completed.

+3
source

For another solution, we added the encoding / json to add the new MarshalSafeCollections() method. This method will march Slices / Arrays / Maps as their corresponding empty values ​​( [] / {} ). Since most of our creation takes place at the data level, we did not want to add code that fixed problems in our http response level. The changes in the library are minimal and follow the releases.

0
source

Source: https://habr.com/ru/post/1233904/


All Articles