Данные Firebase - ошибка преобразования значения - PullRequest
0 голосов
/ 04 мая 2018

Я отправил вопрос относительно базы Firebase два дня назад: Android Firebase - добавить аутентифицированного пользователя в базу данных

Я получил помощь, в которой я нуждался, и это решило первую проблему. Но теперь у меня новая проблема. Я довольно долго гуглял, есть некоторые посты по этой проблеме, но ничего не решило мою проблему. Я не хочу спамить предыдущий вопрос, поэтому я разместил новый.

Когда я пытаюсь прочитать вставленные данные из базы данных Firebase, я получаю эту ошибку:

Newtonsoft.Json.JsonSerializationException: Ошибка преобразования значения «test@user.com», чтобы ввести «carServiceApp.My_Classes.Account». Дорожка «электронная почта», строка 1, позиция 24.

Вот код:

 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;
        }

    }

Это данные пожарной базы:

-users
    -jwAP2dYNzJeiF3QlmEIEQoruUkO2
       email: "test@user.com"
       lastName: "user"
       name: "test"
       phone: "12421"
       uid: "jwAP2dYNzJeiF3QlmEIEQoruUkO2"

Интересно то, что когда я пытаюсь читать данные с помощью:

var items = await firebase.Child("users").OnceAsync<Account>();

Это прекрасно работает (я получаю последний вставленный пользователь). Но когда я добавляю 'uid' узел, я получаю ошибку. Я пытался решить это в течение довольно долгого времени, но я просто не могу понять это. Я предполагаю, что с классом account проблем нет, потому что он работает в случае без узла uid, но не работает при добавлении другого метода child().

Другая информация (код класса учетной записи и способ хранения этих данных в базе данных) вы можете увидеть в ссылке вверху.

Примечание. Я пытался добавить конструктор в класс Account, но это не помогло.

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Предполагалось, что это будет комментарий, но это просто дополнение для тех, кому нужна помощь в решении этой проблемы.

Я знаю, что этот ответ существовал некоторое время, но все еще кажется, что это структурная хитрость с Firebase и использованием их правил. Я столкнулся с этой проблемой со сложной структурой, которая выглядела примерно так

-Orders
    -9876trfghji (User ID)
     -0
       BusnID: "ty890oihg"
       Name: "Some Name"
       AddOns: Object
       ItemData: Object(containing other objects)
       UserID: "9876trfghji"

Примечание. В этом случае, как и в случае с шнурками, вы увидите, что оба конечных объекта имеют идентификатор пользователя или идентификатор пользователя.

Я также столкнулся с проблемой десериализации класса объекта без фактического идентификатора пользователя в данных объектов при его отправке обратно на устройство.

Причиной того, что вы используете «избыточное» использование идентификатора пользователя, является мера безопасности с правилами Firebase. Первый идентификатор пользователя со структурой выше, вы можете контролировать доступ к информации на основе идентификатора пользователя без необходимости наличия дополнительного правила проверки в правилах. В настоящее время с этого поста приведенное ниже правило будет защищать данные на основе идентификатора пользователя.

“Orders” : {
        "$uid":{
                  ".read":"auth != null",
                  ".write":"auth.uid == $uid"
                }
    }

это позволяет пользователю, имеющему только авторизованный идентификатор пользователя, писать контент, но любой, имеющий действительные учетные данные, может просматривать данные.

Второй идентификатор пользователя должен быть помещен в объект, потому что без него вы не сможете выполнить стандартное приведение к объекту, потому что ваш объект не будет иметь всех данных, необходимых для создания объекта. Независимо от того, используете ли вы такой пакет, как GoogleGson или Newtonsoft.Json, объект все еще не заполнен.

Однако существует обходной путь для этой проблемы, кроме повторного ввода идентификатора пользователя в объект. С объектом, который у меня есть выше, я решил просто повторно ввести идентификатор пользователя в моем личном коде, чтобы сэкономить время и хлопоты при создании вручную.

Используя пакет NuGet в Firebase.Database, вы можете создать объект вручную. Вот пример проблемы с объектом в кордах

    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;                        
            }
        }
    }
}

Обновление Есть кое-что, о чем я хотел бы упомянуть, что я не учел при написании этого, и это использование пакета Firebase.Database NuGet с пакетом Gson NuGet и библиотекой Newtonsoft.Json

Если вы решите использовать библиотеку FIrebase.Database, просто знайте, что вы будете работать очень близко с библиотеками Java.Lang и Java.Util. Такие объекты, как Java.Lang.Object, могут быть очень сложными и трудоемкими для написания кода, необходимого для десериализации данных, но не бойтесь, что Gson здесь!

Пакет Gson, если вы разрешите, может отнять у вас большую нагрузку для десериализации класса, если вы позволите. Gson - это библиотека, которая позволит вам выполнять десериализацию строк Java.Lang.Obj в json. Я знаю, что это кажется странным, передавай объект, возвращай строку, звучит противно интуитивно, я знаю, но терпеть меня.

Вот пример того, как нам использовать библиотеку Gson с проблемой связанного объекта.

 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
        }

Для тех, кто может столкнуться с этим в будущем, я надеюсь, что это поможет

0 голосов
/ 15 мая 2018

Хорошо, я точно не нашел решения этой проблемы, и при этом я не понимаю, почему это произошло, но я нашел обходной путь. Я считаю, что это не идеальное решение и что оно не решает существующую проблему. Или, может быть, проблема была в том, что я не понимал логику пожарной базы, но вот что я придумал.

Итак, учитывая, что все работало нормально, если я не указывал этот uid-узел, было очевидно, что возникла некоторая проблема с классом и данными в базе данных, думаю, проблема с соответствием. В любом случае, я решил использовать этот последний узел uid, чтобы я мог выбрать конкретного пользователя, а также иметь те же данные в базе данных, что и в случае, когда все это работало. Итак, вот как я вставил данные в базу данных:

  var item = firebase.Child("users").Child(id).PostAsync<Account>(user);

Это созданный пользовательский узел и дочерний узел. А метод PostAsync создал еще один узел со случайным ключом. Поэтому, когда я пытался читать с этим:

var data = await firebase.Child("users").Child(id).OnceAsync<Account>();

Работало без проблем. Теперь данные Firebase выглядят так:

   users
     JPKdQbwcXbhBatZ2ihBNLRauhV83
        -LCXyLpvdfQ448KOPKUp 
              email:  "spider@man.com"
              lastName:  "man"
              name:  "spider"
              phone:  "14412"
              uid: "JPKdQbwcXbhBatZ2ihBNLRauhV83"

Существует некоторая избыточность, у меня в основном два идентификатора, но я не понимаю, как создать свой класс, чтобы я мог получить эти данные любым другим способом, поэтому я сделал это таким образом. Работает нормально.

Если у кого-то есть лучшее решение, я с удовольствием его поменяю. Приветствия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...