GodotNuts / GodotFirebase

Implementations of Firebase for Godot using GDScript
MIT License
558 stars 79 forks source link

[BUG] document.get_value() returns wrong type and data #426

Closed iNxmi closed 2 months ago

iNxmi commented 2 months ago

Describe the bug when trying to retrieve an integer from a firestore document via document.get_value() the returned type is String

when trying to retrieve a array from a firestore document via document.get_value() the returned type is Dictionary and the dictionary is basically the raw document

To Reproduce

Example code to reproduce bug

extends Node2D

func _ready() -> void:
    Firebase.Auth.login_succeeded.connect(on_login_succeeded)

    if not Firebase.Auth.check_auth_file():
        var provider: AuthProvider = Firebase.Auth.get_GoogleProvider()
        Firebase.Auth.get_auth_localhost(provider, 8060)

func on_login_succeeded(auth):
    Firebase.Auth.save_auth(auth)

    var collection: FirestoreCollection = Firebase.Firestore.collection("test")

    var test_data = {
        "test_string": "this is a string for testing",
        "test_int": 1234,
        "test_float": 98.76,
        "test_array": ["string_a", "string_b"],
        "test_dict": {"key_a": "value_a", "key_b": 0.123, "key_c": 1234}
    }
    var doc_name: String = "test_document"
    await collection.add(doc_name, test_data)

    var document = await collection.get_doc(doc_name)
    print(document)

    for key in document.keys():
        var value = document.get_value(key)
        print("Key: %s" % key)
        print("Type: %s" % type_string(typeof(value)))
        print("Value: %s" % value)
        print("")

Current output

doc_name: test_document, 
data: { "test_int": { "integerValue": "1234" }, "test_array": { "arrayValue": { "values": [{ "stringValue": "string_a" }, { "stringValue": "string_b" }] } }, "test_float": { "doubleValue": 98.76 }, "test_dict": { "mapValue": { "fields": { "key_b": { "doubleValue": 0.123 }, "key_c": { "integerValue": "1234" }, "key_a": { "stringValue": "value_a" } } } }, "test_string": { "stringValue": "this is a string for testing" } }, 
create_time: 2024-08-22T13:28:13.538680Z

Key: test_int
Type: String
Value: 1234

Key: test_array
Type: Dictionary
Value: { "values": [{ "stringValue": "string_a" }, { "stringValue": "string_b" }] }

Key: test_float
Type: float
Value: 98.76

Key: test_dict
Type: Dictionary
Value: { "key_b": 0.123, "key_c": 1234, "key_a": "value_a" }

Key: test_string
Type: String
Value: this is a string for testing

Expected output

doc_name: test_document, 
data: { "test_int": { "integerValue": "1234" }, "test_array": { "arrayValue": { "values": [{ "stringValue": "string_a" }, { "stringValue": "string_b" }] } }, "test_float": { "doubleValue": 98.76 }, "test_dict": { "mapValue": { "fields": { "key_b": { "doubleValue": 0.123 }, "key_c": { "integerValue": "1234" }, "key_a": { "stringValue": "value_a" } } } }, "test_string": { "stringValue": "this is a string for testing" } }, 
create_time: 2024-08-22T13:28:13.538680Z

Key: test_int
Type: int
Value: 1234

Key: test_array
Type: Array
Value: ["string_a", "string_b"]

Key: test_float
Type: float
Value: 98.76

Key: test_dict
Type: Dictionary
Value: { "key_b": 0.123, "key_c": 1234, "key_a": "value_a" }

Key: test_string
Type: String
Value: this is a string for testing

as you can see, the test_int type is somehow a string and the test_arraytype is a dictionary which is derived fo the raw contents of the document. also the integer is stored as a string with quotation marks

"test_int": { "integerValue": "1234" }

Edit as it seems the problem with the array is an easy fix. in the Utilities.gs file is this piece of code

static func from_firebase_type(value : Variant) -> Variant:
    if value == null:
        return null

    if value.has("mapValue"):
        value = fields2dict(value.values()[0])
        #this is missing in the main code so i just added this and now it can retrieve the array
    #if value.has("arrayValue"):
    #   value = fields2array(value.values()[0])
    elif value.has("timestampValue"):
        value = Time.get_datetime_dict_from_datetime_string(value.values()[0], false)
    else:
        value = value.values()[0]