Dynami c Список в флаттере для Json - PullRequest
0 голосов
/ 18 февраля 2020

Я работаю с некоторыми сложными json в дротике, и у меня есть проблема с созданием объектов, прежде чем я знаю, какого типа они будут.

Я ценю предложения, но я не думаю, Я полностью понимаю. В данном ответе:

var entity = Model();
  castToEntity(entity, {'test': 10});

Разве мне не нужно знать, что это будет класс Model? Что делать, если у меня есть два следующих класса:

@JsonSerializable(explicitToJson: true, includeIfNull: false)
class Location {
  String id;
  String resourceType;
Location({@required this.id, this.resourceType})
factory Location.fromJson(Map<String, dynamic> json) => _$LocationFromJson(json);
  Map<String, dynamic> toJson() => _$LocationToJson(this);
}
class Reference {
  String reference;
  String resourceType;
Location({@required this.reference, this.resourceType}
factory Reference.fromJson(Map<String, dynamic> json) => _$ReferenceFromJson(json);
  Map<String, dynamic> toJson() => _$ReferenceToJson(this);
}

И затем я запрашиваю сервер, и я не знаю, какой это будет класс. Это может быть Location, или Reference, или, если это список, он может быть кратным обоим, и я не знаю, пока не запросил его.

var myBundle = Bundle.fromJson(json.decode(response.body));

Each "myBundle.entry "это еще один ресурс. Я хотел бы иметь возможность использовать информацию из этого ресурса, чтобы определить себя. Таким образом, я мог бы сделать что-то вроде:

myBundle.entry.resourceType newResource = new myBundle.entry.resourceType();

То, что я сейчас делаю, это отправка функции, которая имеет все предопределенные возможные параметры:

var newResource = ResourceTypes(myBundle.entry[i].resource.resourceType,
                    myBundle.entry[i].resource.toJson());

dynamic ResourceTypes(String resourceType, Map<String, dynamic> json) {
  if (resourceType == 'Location') return (new Location.fromJson(json));
  if (resourceType == 'Reference') return (new Reference.fromJson(json));
}

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

1 Ответ

0 голосов
/ 18 февраля 2020

Насколько я знаю, это невозможно, поскольку в Dart нет Reflection, как, например, c#, самое близкое, что я могу себе представить, - использование абстрактного класса, который заставляет вашу сущность реализовать fromJson, и в этом методе вы читаете карту и помещаете значения в поля, как показано в коде ниже:

abstract class Serializable {
  void fromJson(Map<String,dynamic> data);
}

class Model implements Serializable {

  int test;
  @override
  void fromJson(data) {
    test = data['test'];
  }
}

Serializable castToEntity(Serializable entity, Map<String, dynamic> data) {
  return entity..fromJson(data);
}

Теперь, когда вы читаете свою базу данных и имеете карту, вы можете вызвать метод generi c например:

var entity = Model();
  castToEntity(entity, {'test': 10});

  print(entity.test);

Где сущность является пустой моделью.

Примечание: Ваши поля в сущности не могут быть окончательными, поскольку из Json - это метод экземпляра, а не фабричный метод.

...