Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialization fails when using generic types #101

Closed
caneva20 opened this issue Dec 4, 2020 · 6 comments
Closed

Deserialization fails when using generic types #101

caneva20 opened this issue Dec 4, 2020 · 6 comments
Assignees
Labels
bug Something isn't working flutter.web issue occurs only in flutter web target

Comments

@caneva20
Copy link

caneva20 commented Dec 4, 2020

Hello @k-paxian! I'm here once again 😃

So, given the following models:

@jsonSerializable
class Foo {}

@jsonSerializable
abstract class BarBase<T> {
  T foo;
}

@jsonSerializable
class Bar extends BarBase<Foo> {}

I get the following error when trying to deserialize it:

Unhandled exception:
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Foo' of 'value'
#0      BarBase.foo= (file:///C:/dev/flutter/json_tests/bin/task.dart)
#1      _data.<anonymous closure> (file:///C:/dev/flutter/json_tests/bin/main.mapper.g.dart:25:3302)
#2      _InstanceMirrorImpl.invokeSetter (package:reflectable/src/reflectable_builder_based.dart:355:20)
#3      JsonMapper._deserializeObject.<anonymous closure> (package:dart_json_mapper/src/mapper.dart:881:12)
#4      JsonMapper._enumeratePublicProperties (package:dart_json_mapper/src/mapper.dart:457:14)
#5      JsonMapper._deserializeObject (package:dart_json_mapper/src/mapper.dart:836:5)
#6      JsonMapper.deserialize (package:dart_json_mapper/src/mapper.dart:62:21)
#7      main (file:///C:/dev/flutter/json_tests/bin/main.dart:12:25)

my main():

void main() {
  initializeJsonMapper();

  var bar = Bar()..foo = Foo();

  var json = JsonMapper.serialize(bar);
  var bar2 = JsonMapper.deserialize<Bar>(json);
}
  • If I use var bar = Bar(); it works fine.
  • I've tried using a template, but the same thing happens.
  • I've tried putting @Json(typeNameProperty: 'typeName') on Foo and BarBase, but it doesn't seem to help.

I understand that what I'm trying to do is kinda weird (why would someone want to do it like that?), and if that is not possible to do (not a bug) that's fine, I'll find an alternative.

@k-paxian k-paxian added the question Further information is requested label Dec 5, 2020
k-paxian added a commit that referenced this issue Dec 5, 2020
@k-paxian
Copy link
Owner

k-paxian commented Dec 5, 2020

Generics are tough in terms of deserialization 🤷

Anyway, I've got some examples for you

Hope this helps somehow 😄

@k-paxian k-paxian assigned k-paxian and unassigned k-paxian Dec 5, 2020
@k-paxian k-paxian closed this as completed Dec 5, 2020
@masoodmrx
Copy link

Hello @k-paxian

I have the same problem, but the error is different

image
my main()

void main() {
  initializeJsonMapper();
  String json = '{"Success":true,"Result":{"Id":1,"Name":"aa"}}';
  ApiResult<UserModel>? result = JsonMapper.deserialize<ApiResult<UserModel>>(json);

...
}

my models

@jsonSerializable
class ApiResult<T> {
  bool? Success;
  T? Result;

  ApiResult({
    this.Success,
    this.Result,
  });

  ApiResult<T>? fromJson(dynamic json) =>
      JsonMapper.deserialize<ApiResult<T>>(json);

  dynamic toJson() =>
      JsonMapper.serialize(this, SerializationOptions(indent: ''));
}

@jsonSerializable
class UserModel {
  int? Id;
  String? Name;

  UserModel({
    this.Id,
    this.Name,
  });
}

@jsonSerializable
@Json(valueDecorators: ApiResultUserModel.valueDecorators)
class ApiResultUserModel extends ApiResult<UserModel> {
  static Map<Type, ValueDecoratorFunction> valueDecorators() =>
      {typeOf<ApiResult<UserModel>>(): (value) => ApiResultUserModel.of(value)};

  ApiResultUserModel({
    bool? Success,
    UserModel? Result,
  }) : super(
          Success: Success,
          Result: Result,
        );

  factory ApiResultUserModel.of(ApiResult other) => ApiResultUserModel(
        Success: other.Success,
        Result: other.Result,
      );
}

Serialization is done without errors

The package you produced is very simple and practical compared to other packages 👍

@k-paxian k-paxian reopened this Jan 6, 2022
k-paxian added a commit that referenced this issue Jan 6, 2022
@k-paxian
Copy link
Owner

k-paxian commented Jan 6, 2022

@masoodmrx Thank you for reporting that, I've got your use case working at this commit.

Anyway, the ApiResultUserModel class is an obvious overhead to simulate generics support, which makes generics not generics anymore 😞

I've got a future plan to handle generics in a more clean way, just like this copy cat package does, due to lack of time this might be not soon enough 🤷

@k-paxian k-paxian closed this as completed Jan 6, 2022
@masoodmrx
Copy link

masoodmrx commented Jan 7, 2022

Hello @k-paxian

The error I sent above has not been resolved yet and only gives this error in the web browser
Please solve the problem, I need it
Thank you very much ❤️

@k-paxian k-paxian added release.apk issue occurs in release mode only bug Something isn't working labels Jan 7, 2022
@k-paxian k-paxian reopened this Jan 7, 2022
@k-paxian k-paxian added flutter.web issue occurs only in flutter web target and removed release.apk issue occurs in release mode only labels Jan 7, 2022
k-paxian added a commit that referenced this issue Jan 7, 2022
#101 (fix) Deserialization fails on flutter web target when using generic types
@k-paxian
Copy link
Owner

k-paxian commented Jan 7, 2022

With version2.2.1 and those models below, seems OK now, please confirm on your side.

@jsonSerializable
class ApiResult<T> {
  bool? Success;
  T? Result;

  ApiResult({
    this.Success,
    this.Result,
  });

  ApiResult<T>? fromJson(dynamic json) =>
      JsonMapper.deserialize<ApiResult<T>>(json);

  dynamic toJson() =>
      JsonMapper.serialize(this, SerializationOptions(indent: ''));
}

@jsonSerializable
class UserModel {
  int? Id;
  String? Name;

  UserModel({
    this.Id,
    this.Name,
  });
}

@jsonSerializable
@Json(valueDecorators: ApiResultUserModel.valueDecorators)
class ApiResultUserModel extends ApiResult<UserModel> {
  static Map<Type, ValueDecoratorFunction> valueDecorators() =>
      {typeOf<ApiResult<UserModel>>(): (value) => ApiResultUserModel.of(value)};

  ApiResultUserModel({
    bool? Success,
    UserModel? Result,
  }) : super(
          Success: Success,
          Result: Result,
        );

  factory ApiResultUserModel.of(ApiResult other) => ApiResultUserModel(
        Success: other.Success,
        Result: JsonMapper.deserialize<UserModel>(other.Result), /// <= Attention: here is the change
      );
}

@k-paxian k-paxian removed the question Further information is requested label Jan 7, 2022
@masoodmrx
Copy link

Error fixed
Thank you very much ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working flutter.web issue occurs only in flutter web target
Projects
None yet
Development

No branches or pull requests

3 participants