'How can I print out the content of a Dictionary<string, object>?
Firebase Databse Fails to download data when needed in between other similar operations in app.
System.Collections.Generic.Dictionary`2[System.String,System.Object]
Firebase Cannot take do new GetValueASync sometimes in middle of similar operations of app and returns System.Collections.Generic.Dictionary`2[System.String,System.Object] as a snapshot value.
Steps to reproduce:
Setup any unity project with realtime databse perform non stop multiple times :
.GetValueAsync().ContinueWithOnMainThread(task =>
then you will get value as System.Collections.Generic.Dictionary`2[System.String,System.Object] instead of any child/key/database value.
public void aaaa() {
Reference.Child("Users").OrderByChild("About/XP").StartAt(1).LimitToFirst(12).GetValueAsync().ContinueWithOnMainThread(task => {
if (task.IsFaulted) {
return;
} else if (task.IsCompleted) {
DataSnapshot Snapshot = task.Result;
if (Snapshot != null)
Debug.Log(Snapshot.Value);
return;
}
return;
});
Solution 1:[1]
Please use loop
foreach( KeyValuePair<string, object> kvp in Snapshot.Value)
{
Console.WriteLine("Key = {0}, Value = {1}",
kvp.Key, kvp.Value);
}
Solution 2:[2]
The "issue"
Well this happens if you use ToString (which is what Debug.Log does internally) on a dictionary or in general any object of a type that doesn't implement it explicitly, it simply returns the same as GetType().FullName.
Default implementations of the
Object.ToStringmethod return the fully qualified name of the object's type.
Firebase.Database.DataSnapshot.Value
returns the data contained in this snapshot as native types. The possible types returned are:
boolstringlongdoubleIDictionary{string, object}List{object}This list is recursive; the possible types for object in the above list is given by the same list.
These types correspond to the types available in JSON.
So it looks like in your case the type is a Dictionary<string, object>.
You can easily confirm this
Debug.Log(new Dictionary<string, object>().ToString());
will print
System.Collections.Generic.Dictionary`2[System.String,System.Object]
Solution 1a - Simple Loop
If you want to see all first level items you rather want to do e.g.
foreach(var kvp in Snapshot.Value)
{
Debug.Log($"Key: {kvp.Key}, Value: {kvp.Value}");
}
Note though: while the key is a string, the value once again might be a type (afaik e.g. again a Dictionary<string, object>) not implementing ToString in which case again it will simply print out the type name.
Solution 1b - Recursive print
You could of course implement something covering this all recursive, somewhat like e.g. (untested)
public static class SnapthotExtensions
{
public static string GetString(this DataSnapshot snapshot)
{
return GetString(snapshot.Value);
}
private static string GetString(this object obj)
{
var sb = new StringBuilder();
GetString(obj, sb);
return sb.ToString();
}
public static void GetString(object obj, StringBuilder sb, int indent = 1)
{
switch (obj)
{
case bool b:
sb.Append(b);
break;
case string s:
sb.Append('"').Append(s).Append('"');
break;
case long l:
sb.Append(l.ToString());
break;
case double d:
sb.Append(d.ToString("G17"));
break;
case IDictionary<string, object> dict:
{
sb.Append("[\n");
var i = 0;
foreach (var kvp in dict)
{
sb.Append(new string(Enumerable.Repeat(' ', indent * 2).ToArray()));
sb.Append('"');
sb.Append(kvp.Key);
sb.Append("\": ");
GetString(kvp.Value, sb, indent + 1);
if (i < dict.Count - 1) sb.Append(",\n");
i++;
}
sb.Append('\n');
sb.Append(new string(Enumerable.Repeat(' ', indent * 2).ToArray()));
sb.Append(']');
break;
}
case IList iList:
var list = iList.Cast<object>().ToList();
sb.Append("[\n");
for (var i = 0; i < list.Count; i++)
{
sb.Append(new string(Enumerable.Repeat(' ', indent * 2).ToArray()));
GetString(list[i], sb, indent + 1);
if (i < list.Count - 1) sb.Append(",\n");
}
sb.Append('\n');
sb.Append(new string(Enumerable.Repeat(' ', indent * 2).ToArray()));
sb.Append(']');
break;
default:
throw new NotSupportedException($"Type {obj.GetType()} is not supported!");
}
}
}
and then use
Debug.Log(snapshot.GetString());
Solution 2 - Newtonsoft JSON
But if you really want to print out the entire structure (as far as the values are serializable) you could/should rather use Newtonsoft JSON.Net and convert the entire dictionary into a human readable JSON format. Then print out this JSON instead of implementing it yourself.
string json = JsonConvert.SerializeObject(Snapshot.Value, Formatting.Indented);
Debug.Log(json);
Solution 3 - Firebase specific
I found out that Newtonsoft isn't really needed in your specific case! (I'll leave it here as a general hack to print out dictionaries when not using Firebase)
Just use GetRawJsonValue
returns the data contained in this snapshot as a json serialized string.
so it is as simple as
Debug.Log(Snapshot.GetRawJsonValue());
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ganesh Gadekar |
| Solution 2 |
