Правильный способ реализации унаследованных статических методов для десериализации JSON

#json #oop #dart #serialization

Вопрос:

Этот вопрос касается Dart, но может также распространяться и на более широкую «парадигму объектно-ориентированного программирования».

Я пытаюсь создать структуру сериализатора/десериализатора JSON для своего приложения Flutter для взаимодействия с базой данных Firestore. У меня есть набор моделей, которые я создал ( Account , Transaction , и Person ). У меня есть функции для каждой сериализации их в JSON и именованные конструкторы, десериализующие их из JSON. У меня также есть функция, которая создает конвертер для каждой модели интерфейса Firestore в соответствии с руководством на странице учебника Flutter Cloud Firestore, чтобы мне не приходилось десериализовывать / сериализовывать каждую транзакцию с базой данных Firestore в одну из этих моделей.

Я пытаюсь создать общую полиморфную функцию, которая возьмет Account класс , Person , или Transaction и создаст для него конвертер для Firestore. Это выглядит примерно так:

 dynamic createFirestorRef<T extends Entity>(FirebaseFirestore instance) {
  return instance.collection("accounts").withConverter<T>(
        fromFirestore: (snapshot, _) {
          return T.fromJson(snapshot.id, snapshot.data()!);
        },
        toFirestore: (entity, _) => entity.toJson(),
      );
}
 

Где Entity класс «» является общим унаследованным абстрактным классом между тремя другими классами, реализующими .toJson() метод. Однако .fromJson() метод является именованным конструктором сущности и, следовательно, НЕ наследуется дочерними классами и, следовательно, не будет следовать полиморфному поведению, которое .toJson() имеет место. Поэтому эта строка return T.fromJson(snapshot.id, snapshot.data()!); не работает, так как нет способа гарантировать, что классы, наследуемые от сущности, имеют именованный конструктор .fromJson() .

Мой вопрос: как мне воспроизвести это поведение, которое следует общей парадигме ООП?

Dart не имеет ни унаследованных статических методов, ни унаследованных конструкторов. Я не могу реализовать метод экземпляра, потому что на момент десериализации еще нет экземпляра.

Комментарии:

1. Вы можете добиться этого с помощью a Map<Type, Function> , который инициализируется с помощью обратных вызовов, которые вы хотите. Однако типичным способом сериализации/десериализации JSON в Dart является использование генерации кода , что package:json_serializable и package:built_value работает. Я настоятельно рекомендую использовать существующее решение вместо создания собственного.

2. @jamesdlin Благодарим вас за предложения по встроенным библиотекам. Является ли это стандартной практикой для разработки в Дартсе? Новичок в этом языке

3. Как я уже сказал, типичной рекомендацией является использование генерации кода. Десериализация JSON вручную может быть очень подвержена ошибкам.