simc / crimson

Fast, efficient and easy-to-use JSON parser and serializer for Dart.
Apache License 2.0
229 stars 6 forks source link

Incorrect fromJson parameter in README? #18

Open Reprevise opened 1 year ago

Reprevise commented 1 year ago

The README states that the fromJson factory takes a Uint8List as does the fromBytes factory. If that's the case, then what's the difference?

What I believe happened is a copy-paste error as when I try and read a nested Crimson class, Crimson tries to pass a Map<String, dynamic> to the fromJson method of the other class.

Please confirm, thanks!

EDIT: The README also appears to be missing toJson as well.

simc commented 1 year ago

It's not a typo. You can use whichever name you like better. If you want to create a "regular" fromJson with Map<String, dynamic>, Crimson will just ignore it.

Reprevise commented 1 year ago

So I have two types here:

@freezed
class MatchData with _$MatchData {
  @json
  const factory MatchData({
    @Default(<String, dynamic>{}) Map<String, dynamic> attributes,
    @Default(<String, dynamic>{}) Map<String, dynamic> metadata,
    @Default(<Segment>[]) List<Segment> segments,
  }) = _MatchData;

  factory MatchData.fromBytes(Uint8List json) => _$MatchDataFromBytes(json);
}

@freezed
class Segment with _$Segment {
  @json
  const factory Segment({
    String? type,
    @Default(<String, dynamic>{}) Map<String, dynamic> attributes,
    @Default(<String, dynamic>{}) Map<String, dynamic> metadata,
    @Default(<String, Stat>{}) Map<String, Stat> stats,
  }) = _Segment;

  factory Segment.fromBytes(Uint8List json) => _$SegmentFromBytes(json);
}

But in the Crimson-generated file, inside the read method of MatchData it tries calling Segment.fromJson which doesn't exist and when it does exist, it tries passing in a Map<String, dynamic>.

EDIT: Using the fromJson factory constructors for my freezed classes, the generated code is fixed, however this part of the generated code throws an error at runtime as the read() method returns a _Map<String, dynamic> instead of a Uint8List.

segments = skipNull()
    ? null
    : [
        for (; iterArray();) Segment.fromJson(read()),
      ];
frank06 commented 1 year ago

Using factory MatchData.fromJson(Uint8List json) => _$MatchDataFromJson(json); has to be wrong.

Generating the class with this will make the compiler complain:

The argument type 'Uint8List' can't be assigned to the parameter type 'Map<String, dynamic>'.dart[argument_type_not_assignable](https://dart.dev/diagnostics/argument_type_not_assignable)

Changing it to factory MatchData.fromJson(Map<String, dynamic> json) => _$MatchDataFromJson(json); removes the compiler error but, after a build, introduces a new one:

The method '_$$_MatchDataFromJson' isn't defined for the type '_$_MatchData'.
Try correcting the name to the name of an existing method, or defining a method named '_$$_MatchDataFromJson'.dart[undefined_method](https://dart.dev/diagnostics/undefined_method)

(same for _$$_MatchDataToJson)

Do you have a sample app with Freezed and Crimson using toJson/fromJson?

frank06 commented 1 year ago

Apparently @Freezed(fromJson: false, toJson: false) is necessary for it to work, otherwise Freezed starts assuming we use json_serializable and mixes things up.