So I've been playing around with the firebase firestore feature for my REST API backend for a Godot project I'm working on. I'm using HTTP requests to post and get data from the database. So far I've only been using simple types of data, associating one user's ID to his or her username as a string.
In my code, I've defined a function that is responsible for doing the actual saving of a new file through an HTTP request:
func save_document(path: String, fields: Dictionary, http: HTTPRequest) -> void:
var document = { "fields": fields }
var body = to_json(document)
var url = FIRESTORE_URL + path
var res = http.request(url, _get_request_headers(), false, HTTPClient.METHOD_POST, body)
if res == OK:
print("successfully created document")
else:
print("failed creating document")
Then I call the function:
var payload_body_1 = {
"name": {
"stringValue": username.text
}
}
save_document("users?documentId=%s" % firebase.user_info.id, payload_body_1, http)
All of the above works 100% fine. But when I try to post more complicated data, such as a dictionary of dictionaries of dictionaries, I run into some problems.
When I run the following code:
var res = {
"north": {"spades": [], "hearts": [], "diamonds": [], "clubs": []},
"south": {"spades": [], "hearts": [], "diamonds": [], "clubs": []},
"east": {"spades": [], "hearts": [], "diamonds": [], "clubs": []},
"west": {"spades": [], "hearts": [], "diamonds": [], "clubs": []},
}
save_document("online?documentId=test", res, http)
It doesn't work. I imagine it has something to do with the "stringValue" key I used in the case where it worked, but I can't seem to figure out what to do when the value isn't a string value. Does anyone know how to solve this?
Ok so I actually solved it but I thought I might as well post the answer here if someone else potentially has the same problem in the future.
So basically, every field needs a data type, for instance, "stringValue". for Dictionaries, you need "mapValue", and for lists, you need "arrayValue". In the above Example, you would need to use some code looking like this:
var res = {
"north": { "mapValue": { "fields": {
"spades": { "arrayValue": { "values": [] } },
"hearts": { "arrayValue": { "values": [] } },
"diamonds": { "arrayValue": { "values": [] } },
"clubs": { "arrayValue": { "values": [] } }
} } },
"south": { "mapValue": { "fields": {
"spades": { "arrayValue": { "values": [] } },
"hearts": { "arrayValue": { "values": [] } },
"diamonds": { "arrayValue": { "values": [] } },
"clubs": { "arrayValue": { "values": [] } }
} } },
"east": { "mapValue": { "fields": {
"spades": { "arrayValue": { "values": [] } },
"hearts": { "arrayValue": { "values": [] } },
"diamonds": { "arrayValue": { "values": [] } },
"clubs": { "arrayValue": { "values": [] } }
} } },
"west": { "mapValue": { "fields": {
"spades": { "arrayValue": { "values": [] } },
"hearts": { "arrayValue": { "values": [] } },
"diamonds": { "arrayValue": { "values": [] } },
"clubs": { "arrayValue": { "values": [] } }
} } }
}
the mapValues need the "fields" key which is a dictionary of the keys in the dictionary associated with "mapValue". The arrayValues need something similar, but "values" instead of "fields". each element of the array in values should be a dictionary, and if you want the array for example to contain strings, each element should look like:
{ "stringValue": "text" }