Home  >  Article  >  Backend Development  >  Unmarshal Firestore cloud events in protojson format into a mapinterface{} or struct

Unmarshal Firestore cloud events in protojson format into a mapinterface{} or struct

WBOY
WBOYforward
2024-02-13 23:09:08427browse

将 protojson 格式的 Firestore 云事件解组到 mapinterface{} 或结构中

#php editor Zimo will introduce in this article how to unmarshal Firestore cloud events in protojson format into map[interface{}] or structure. Firestore is a flexible document database solution provided by Google Cloud, and protojson is a tool for converting Protocol Buffers data into JSON format. Understanding how to unmarshal Firestore cloud events is an important skill for developers when using Firestore Database. This article will explain in detail the steps and precautions for unmarshalling to help developers better utilize the functions of Firestore Database.

Question content

Is there an easy way to unmarshal firestore data in protojson format into a map[string]interface{} or struct without using all the protobuf data type tags? i.e. flatten protojson data.

I have a google cloud function that is fired whenever a new firebase document is created ("cloud event"). This cloud event contains contextual information, including modified documents in protojson format:

import (
    "google.golang.org/protobuf/encoding/protojson"
    "github.com/davecgh/go-spew/spew"
)

func cloudfunction(ctx context.context, e event.event) error {
    data := firestoredata.documenteventdata{}
    _ = protojson.unmarshal(e.dataencoded, &data);

    spew.dump(data)
}
--------console output--------

{
"oldvalue": {},
"value": {
    "createtime": "2023-03-30t00:00:00.000000z",
    "updatetime": "2023-03-30t00:00:00.000000z",
    "name": "projects/myproject/databases/(default)/documents/collectionname/00000000-0000-0000-0000-000000000000",
    "fields": {
        "id": {
        "stringvalue": "00000000-0000-0000-0000-000000000000"
        },
        "action": {
            "stringvalue": "serverdosomething"
        },
        "payload": {
            "mapvalue": {
                "fields": {
                    "questionslist": {
                        "arrayvalue": {
                            "values": [
                                {
                                    "mapvalue": {
                                        "fields": {
                                            "title": {
                                                "stringvalue": "how do i fly a kite?"
                                            },
                                        }
                                    }
                                },
                                {
                                    "mapvalue": {
                                        "fields": {
                                            "title": {
                                            "stringvalue": "how do i fly a plane?"
                                            },
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
},
"updatemask": {}
}

I want to marshal the chunks of this protojson document into a custom go structure to easily validate each type of entry, like this:

// cloudeventrequest is a struct that wraps around one or more data validation structs contained in the payload
cloudeventrequest {
    id: "00000000-0000-0000-0000-000000000000"
    action: "serverdostuff"
    payload: map{
        "questionslist": []question{
            question{
                title: "how do i fly a kite?"
            },
            question{
                title: "how do i fly a plane?"
            }
        }
    }
}

The firestore sdk includes a datato method that makes it easy to unmarshal protojson formatted data into a custom structure. I'm trying to do something very similar, but already getting the document data outside of the firestore sdk.

// datato uses the document's fields to populate p, which can be a pointer to a map[string]interface{} or a pointer to a struct.

func (*firestore.documentsnapshot).datato(p interface{}) error
import (
    "context"
    "cloud.google.com/go/firestore"
)

func FirestoreRead(docEvent firestoredata.DocumentEventData) error {
    ctx := context.Background()

    ref := h.client.Collection("mycollection").Doc(docEvent.value.ID)
    docSnapshot, err := tx.Get(ref)

    dataValidationStruct := CloudEventRequest{}
    err = docSnapshot.DataTo(&dataValidationStruct)
}

Solution

I wrote an open source Go package called "firestruct" to solve this challenge. You can find it here: github.com/bennovw/firestruct Your feedback and contributions are very welcome!

I ended up writing a function that recursively unpacks Firestore fields into matching maps. I then refactored the DataTo() method in cloud.google.com/go/firestore to unmarshal my map into a struct.

The above is the detailed content of Unmarshal Firestore cloud events in protojson format into a mapinterface{} or struct. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete