C# Firebase数据-转换值时出错
两天前,我发布了有关firebase的问题: 我得到了我需要的帮助,解决了第一个问题。但现在我有了一个新问题。我在谷歌上搜索了很长一段时间,有一些关于这个问题的帖子,但没有解决我的问题。我不想发上一个问题的垃圾邮件,所以我发布了一个新问题 当我尝试从firebase数据库读取插入的数据时,出现以下错误: Newtonsoft.Json.JsonSerializationException:转换值时出错 "test@user.com“输入'carServiceApp.My_Classes.Account'。路径 “电子邮件”,第1行,第24位 代码如下:C# Firebase数据-转换值时出错,c#,json,firebase,firebase-realtime-database,xamarin.android,C#,Json,Firebase,Firebase Realtime Database,Xamarin.android,两天前,我发布了有关firebase的问题: 我得到了我需要的帮助,解决了第一个问题。但现在我有了一个新问题。我在谷歌上搜索了很长一段时间,有一些关于这个问题的帖子,但没有解决我的问题。我不想发上一个问题的垃圾邮件,所以我发布了一个新问题 当我尝试从firebase数据库读取插入的数据时,出现以下错误: Newtonsoft.Json.JsonSerializationException:转换值时出错 "test@user.com“输入'carServiceApp.My_Classes.Acc
private async Task LoadData()
{
FirebaseUser users = FirebaseAuth.GetInstance(loginActivity.app).CurrentUser;
id = users.Uid;
var firebase = new FirebaseClient(loginActivity.FirebaseURL);
var items = await firebase.Child("users").Child(id).OnceAsync<Account>();
foreach (var item in items)
{
Account user = new Account();
user.uid = item.Object.uid;
user.name = item.Object.name;
user.lastName = item.Object.lastName;
user.phone = item.Object.phone;
user.email = item.Object.email;
userInput_ime.Text = user.name;
userInput_prezime.Text = user.lastName;
userInput_broj.Text = user.phone;
userInput_email.Text = user.email;
}
}
有趣的是,当我尝试用以下方法读取数据时:
var items = await firebase.Child("users").OnceAsync<Account>();
var data = await firebase.Child("users").Child(id).OnceAsync<Account>();
var items=await firebase.Child(“用户”).OnceAsync();
这很好(我得到最后一个插入的用户)。但当我添加'uid'
节点时,我得到了错误。我试图解决这个问题已经有一段时间了,但我就是想不出来。我想account类没有问题,因为它在没有uid
节点的情况下工作,但在添加另一个child()
方法时不工作
您可以在顶部的链接中看到其他信息(帐户类别代码和将数据存储到数据库中的方式)
注意:我尝试在Account类中添加构造函数,但没有帮助 好的,所以我没有找到解决这个问题的方法,也不知道为什么会发生这种情况,但我找到了解决办法。我认为这不是理想的解决方案,也不能解决现有的问题。或者可能是我不理解firebase逻辑的问题,但下面是我的想法 所以,考虑到若我并没有指定uid节点,那个么一切都可以正常工作,很明显firebase中的类和数据存在一些问题,我猜是匹配问题。无论如何,我决定使用最后一个uid节点,这样我就可以选择特定的用户,并且在firebase中拥有与它相同的数据,以防所有这些都正常工作。我就是这样将数据插入firebase的:
var item = firebase.Child("users").Child(id).PostAsync<Account>(user);
有一点冗余,我基本上有两个ID,但我不知道如何创建我的类,以便我可以以任何其他方式获取数据,所以我这样做了。它很好用
如果有人有更好的解决办法,我会很高兴地改变它。干杯这本应该是一个评论,但这只是为任何需要帮助解决这个问题的人添加的 我知道这个答案已经存在了一段时间,但这似乎仍然是Firebase的一个运行结构怪癖以及它们规则的使用。我遇到了这个问题,有一个复杂的结构,看起来有点像这样
-Orders
-9876trfghji (User ID)
-0
BusnID: "ty890oihg"
Name: "Some Name"
AddOns: Object
ItemData: Object(containing other objects)
UserID: "9876trfghji"
注意:在本例中以及使用cordas的情况下,您将看到最后两个对象都有一个用户ID或uid
在将对象发送回设备时,我还遇到了对象的类反序列化问题,而对象数据中没有实际的用户ID
用户id的“冗余”使用是为了使用Firebase规则进行安全措施。第一个具有上述结构的UserID,您可以基于UserID控制对信息的访问,而不必在规则中有额外的验证子句。目前为止,以下规则将根据用户ID保护数据
“Orders” : {
"$uid":{
".read":"auth != null",
".write":"auth.uid == $uid"
}
}
这允许仅具有授权用户id的用户写入内容,但任何具有有效凭据的人都可以查看数据
第二个用户ID必须放置在对象中,因为没有它,您将无法对对象执行标准转换,因为您的对象将不具有创建对象所需的所有数据。无论您使用的是GoogleGson或Newtonsoft.Json之类的包,对象仍然未满
除了将用户ID重新输入到对象中之外,还有一个解决此问题的方法。对于上面的对象,我决定在我的个人代码中重新输入用户ID,以节省手动创建的时间和麻烦
使用Firebase.Database NuGet包,您可以手动创建对象。下面是cordas问题中对象的一个示例
public static void GetUser_Firebase(User user, FirebaseApp app)
{
FirebaseDatabase database = FirebaseDatabase.GetInstance(app);
DatabaseReference reference = database.GetReference($"/users/{user.UserID}");
//"Using for getting firebase information", $"/users/{user.UserID}"
reference.AddListenerForSingleValueEvent(new UserInfo_DataValue());
}
class UserInfo_DataValue : Java.Lang.Object, IValueEventListener
{
private string ID;
public UserInfo_DataValue(string uid)
{
this.ID = uid;
}
public void OnCancelled(DatabaseError error)
{
//"Failed To Get User Information For User "
}
public void OnDataChange(DataSnapshot snapshot)
{
Dictionary<string, string> Map = new Dictionary<string, string>();
var items = snapshot.Children?.ToEnumerable<DataSnapshot>(); // using Linq
foreach(DataSnapshot item in items)
{
try
{
Map.Add(item.Key, item.Value.ToString()); // item.value is a Java.Lang.Object
}
catch(Exception ex)
{
//"EXCEPTION WITH DICTIONARY MAP"
}
}
User toReturn = new User();
toReturn.UserID this.ID;
foreach (var item in Map)
{
switch (item.Key)
{
case "email":
toReturn.email = item.Value;
break;
case "lastName":
toReturn.lastName = item.Value;
break;
case "name":
toReturn.name = item.Value;
break;
case "phone":
toReturn.phone = item.Value;
break;
}
}
}
}
public static void GetUser\u Firebase(用户用户,FirebaseApp)
{
FirebaseDatabase=FirebaseDatabase.GetInstance(应用程序);
DatabaseReference=database.GetReference($“/users/{user.UserID}”);
//用于获取firebase信息“,$”/users/{user.UserID}”
reference.AddListenerForSingleValueEvent(新的UserInfo_DataValue());
}
类UserInfo_DataValue:Java.Lang.Object,IValueEventListener
{
私有字符串ID;
公共用户信息数据值(字符串uid)
{
this.ID=uid;
}
已取消的公共无效(DatabaseError错误)
{
//“无法获取用户的用户信息”
}
公共无效OnDataChange(数据快照快照)
{
字典映射=新字典();
var items=snapshot.Children?.ToEnumerable();//使用Linq
foreach(项目中的DataSnapshot项目)
{
尝试
{
Map.Add(item.Key,item.Value.ToString());//item.Value是一个Java.Lang.Object
}
捕获(例外情况除外)
{
//“字典映射异常”
}
}
用户返回=新用户();
toReturn.UserID this.ID;
foreach(映射中的变量项)
{
开关(项目.钥匙)
{
案例“电子邮件”:
toReturn.email=item.Value;
打破
案例“lastName”:
toReturn.lastName=item.Value;
打破
案例“名称”:
toReturn.name=item.Value;
打破
案例“电话”:
toReturn.phone=item.Value;
打破
“Orders” : {
"$uid":{
".read":"auth != null",
".write":"auth.uid == $uid"
}
}
public static void GetUser_Firebase(User user, FirebaseApp app)
{
FirebaseDatabase database = FirebaseDatabase.GetInstance(app);
DatabaseReference reference = database.GetReference($"/users/{user.UserID}");
//"Using for getting firebase information", $"/users/{user.UserID}"
reference.AddListenerForSingleValueEvent(new UserInfo_DataValue());
}
class UserInfo_DataValue : Java.Lang.Object, IValueEventListener
{
private string ID;
public UserInfo_DataValue(string uid)
{
this.ID = uid;
}
public void OnCancelled(DatabaseError error)
{
//"Failed To Get User Information For User "
}
public void OnDataChange(DataSnapshot snapshot)
{
Dictionary<string, string> Map = new Dictionary<string, string>();
var items = snapshot.Children?.ToEnumerable<DataSnapshot>(); // using Linq
foreach(DataSnapshot item in items)
{
try
{
Map.Add(item.Key, item.Value.ToString()); // item.value is a Java.Lang.Object
}
catch(Exception ex)
{
//"EXCEPTION WITH DICTIONARY MAP"
}
}
User toReturn = new User();
toReturn.UserID this.ID;
foreach (var item in Map)
{
switch (item.Key)
{
case "email":
toReturn.email = item.Value;
break;
case "lastName":
toReturn.lastName = item.Value;
break;
case "name":
toReturn.name = item.Value;
break;
case "phone":
toReturn.phone = item.Value;
break;
}
}
}
}
public static void Get_User(User user, FirebaseApp app)
{
FirebaseDatabase database = FirebaseDatabase.GetInstance(app);
DatabaseReference reference = database.GetReference($"Users/{user.UserID}");
reference.AddListenerForSingleValueEvent(new User_DataValue(user, app));
//$"Trying to make call for user orders Users/{user.UserID}");
}
class User_DataValue : Java.Lang.Object, IValueEventListener
{
private User User;
private FirebaseApp app;
public UserOrderID_Init_DataValue(User user, FirebaseApp app)
{
this.User = user;
this.app = app;
}
public void OnCancelled(DatabaseError error)
{
//$"Failed To Get User Orders {error.Message}");
}
public void OnDataChange(DataSnapshot snapshot)
{
//"Data received for user orders");
var gson = new GsonBuilder().SetPrettyPrinting().Create();
var json = gson.ToJson(snapshot.Value); // Gson extention method obj -> string
Formatted_Output("Data received for user order json ", json);
User user = JsonConvert.DeserializeObject<User>(json); //Newtonsoft.Json extention method string -> object
//now the user is a fully populated object with very little work
}