TiagoH
TiagoH

Reputation: 65

Cloud Function Firestore Trigger with document using inaccurate number fields

I'm implementing a firestore trigger in GoLang, which will listen to changes on a collection and with, will create a new document on a different collection.

So far so good, I had a look into the official documentation here: https://cloud.google.com/functions/docs/calling/cloud-firestore#event_structure which gives an example on how we can use a custom sruct (here represented as MyData) like so:

// FirestoreValue holds Firestore fields.
type FirestoreValue struct {
        CreateTime time.Time `json:"createTime"`
        // Fields is the data for this value. The type depends on the format of your
        // database. Log an interface{} value and inspect the result to see a JSON
        // representation of your database fields.
        Fields     MyData    `json:"fields"`
        Name       string    `json:"name"`
        UpdateTime time.Time `json:"updateTime"`
}

// MyData represents a value from Firestore. The type definition depends on the
// format of your database.
type MyData struct {
        Original struct {
                StringValue string `json:"stringValue"`
        } `json:"original"`
}

And that works fine. Now where it gets trickier is if our document has a number instead of a string, like:

type MyOtherData struct {
        Original struct {
                DoubleValue float64 `json:"doubleValue"`
        } `json:"original"`
}

Everything seems fine, and in fact it works, but only if the document has a number with a decimal part, like: 1.2. However, if this document happens to have a value without decimal part, like: 1, then the number comes decoded to MyOtherData as 0.

Edited:

Ok, now I get why it's 0, because in fact, firestore doesn't distinguish between integer and float, and that makes the object coming with (in json):

"fields":{"original":{"doubleValue":3.5}

if the document has a value with a decimal part. But comes with:

"fields":{"original":{"integerValue":"3"}

if the document has no decimal part.

Does anyone knows how should this be handled elegantly? I would like to avoid using interface{} for this cases...

Thanks in advance :)

Upvotes: 1

Views: 128

Answers (1)

TiagoH
TiagoH

Reputation: 65

So, the better option I found was to change my struct like this:

type MyOtherData struct {
        Original FirestoreNumber `json:"original"`
}

type FirestoreNumber struct {
    DoubleValue  float64 `json:"doubleValue"`
    IntegerValue int     `json:"integerValue,string"`
}

func (fn *FirestoreNumber) Value() float64 {
    if fn.IntegerValue != 0 {
        return float64(fn.IntegerValue)
    }

    return fn.DoubleValue
}

Then, instead of accessing directly myOtherData.Original.DoubleValue, I do myOtherData.Original.Value()

If someone knows a better option, please share :)

Upvotes: 1

Related Questions