[GODRIVER-2163] omitempty doesnt work on primitive.Decimal128 (json) Created: 25/Sep/21  Updated: 27/Oct/23  Resolved: 20/Oct/21

Status: Closed
Project: Go Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Shadoweb EB Assignee: Benji Rewis (Inactive)
Resolution: Gone away Votes: 0
Labels: post-1.8.0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Documentation Changes: Not Needed

 Description   

Hi,

This is related to the issue GODRIVER-1783 the `bson:"field,omitempty"` works, but not 

`json:"field,omitempty"` the return will be

{cost: "0E-6176"}

 Comments   
Comment by Benji Rewis (Inactive) [ 20/Oct/21 ]

Right it is similar to primitive.ObjectID in that sense. If for some reason using a pointer does not work, feel free to reopen/comment on this ticket!

Thanks again for your report shadowbob45@gmail.com!

Comment by Shadoweb EB [ 20/Oct/21 ]

Yes indeed that does the trick, it's the same as primitive.ObjectID.

I thought it would be possible to change it in the Marshal directly, but it's OK I can live with that.

Thanks for your time.

Comment by Benji Rewis (Inactive) [ 19/Oct/21 ]

Apologies for the delay, shadowbob45@gmail.com.

So I think making Field a pointer to a primitive.Decimal128 (*primitive.Decimal128) instead of a regular primitive.Decimal128 should fix the issue you’re seeing.

Here’s what I believe is happening. Field is of type primitive.Decimal128, so when you do not specify it on your creation of something := Something, something.Field is a primitive.Decimal128 with h == 0 and l == 0. The call to d.String() here will attempt to stringify that primitive.Decimal128 and ends up with “0E-6176” (I won’t get into the semantics of that strange negative exponent here). String() does not know the difference between a primitive.Decimal128 that is equivalent to 0 and one that was not explicitly set but just has the zero-values for h and l. So, it returns “0E-6176” either way. json.Marshal() will not recognize that as “empty” and thus “field” will not be omitted from the marshaled bytes.

If Field is a pointer to a primitive.D, however, when you do not specify it on your creation of something := Something, something.Field will be nil (the zero-value of a pointer). Your call to json.Marshal() will see that Field is nil, recognize it as "empty" and thus omit "field" from the marshaled bytes.

In GODRIVER-1783, we could simply implement IsZero for Decimal128. There is not a similar function for the JSON library, so a pointer to a primitive.Decimal128 may have to do. Let me know if that doesn’t work or I’m still misunderstanding your issue.

Comment by Shadoweb EB [ 16/Oct/21 ]

Yes correct, the code below will output {"field": "0E-6176"}. It's not dramatic, but it's better to have it empty when there are big JSON files returned by REST API.

 

type Something struct {
    Field primitive.Decimal128 `json:"field,omitempty"`
}
something := Something{}
data, _ := json.Marshal(something)
fmt.Println(string(data)) // {"field": "0E-6176"}

Thanks
 

Comment by Benji Rewis (Inactive) [ 08/Oct/21 ]

Hello again, shadowbob45@gmail.com! Thanks again for the report.

Could you include the code you're using? What do you mean `json:"field,omitempty"` "returns" {cost: "0E-6176"}?

Are you doing something like:

type Something struct {            Field primitive.Decimal128 `json:"field,omitempty"`}something := Something{} 
bsonSomething, err := bson.Marshal(something) 
assert.Nil(t, err, "Marshal error: %v", err)
 
var doc bson.D 
err = bson.Unmarshal(bsonSomething, &doc) 
assert.Nil(t, err, "Unmarshal error: %v", err)

And finding that doc is bson.D{{field, 0E-6176}}?

Comment by Shadoweb EB [ 03/Oct/21 ]

Hi Kevin, I'm using Go driver v1.7.2.

Comment by Kevin Albertson [ 27/Sep/21 ]

Hi shadowbob45@gmail.com, thank you for the report. We will look into this soon. What version of the Go driver are you using?

Generated at Thu Feb 08 08:37:57 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.