riverpod icon indicating copy to clipboard operation
riverpod copied to clipboard

Use JsonSerializable for JsonPersist

Open TekExplorer opened this issue 8 months ago • 2 comments

Is your feature request related to a problem? Please describe. Currently, @JsonPersist() can and will generate code that will not compile if it does not have a T.fromJson(json)

Describe the solution you'd like Rather than reinvent the wheel, I'd honestly go the freezed route and generate it like so;

class Demo extends _$Demo {
  @JsonKey(...)
  @SomeJsonConverter()
  FutureOr<int> build() {...}
}


abstract class _$Demo extends _$DemoBase {
  String get key {...}

  /// A variant of [persist], for JSON-specific encoding.
  ///
  /// You can override [key] to customize the key used for storage.
  PersistResult persist(
    FutureOr<Storage<String, String>> storage, {
    String? key,
    String Function(int state)? encode,
    int Function(String encoded)? decode,
    StorageOptions options = const StorageOptions(),
  }) {
    return NotifierPersistX(this).persist<String, String>(
      storage,
      key: key ?? this.key,
      encode:
          encode ??
          (state) {
            final json = _$$DemoSerializerToJson(_$DemoSerializer(state));
            return $jsonCodex.encode(json['value']);
          },
      decode:
          decode ??
          (encoded) {
            final json = $jsonCodex.decode(encoded);
            return _$$DemoSerializerFromJson({'value': json}).value;
          },
      options: options,
    );
  }
}

@JsonSerializable()
class _$DemoSerializer {
  _$DemoSerializer(this.value);
  @JsonKey(...)
  @SomeJsonConverter()
  final int value;
}

Then, all we'd need is to forward annotations from build() to that field and we're most of the way there.

All that remains is generic_argument_factories support, and we're golden.

This does mean we'd need another part file, but lets be honest, thats the fault of the current tools more than anything else.

Optionally accept JsonSerialisable arguments in JsonPersist

Describe alternatives you've considered We could choose to simply not generate when there is no T.fromJson

TekExplorer avatar Aug 28 '25 22:08 TekExplorer

At minimum this would require two part, because when using .g.dart for Riverpod, json_serializable won't run on the generated code.

Also the Freezed route isn't perfect. There are loads of bugs and unexpected warnings :)

rrousselGit avatar Aug 28 '25 22:08 rrousselGit

At minimum this would require two part, because when using .g.dart for Riverpod, json_serializable won't run on the generated code.

Yes, I acknowledged that. The tooling needs to get better on that front to be honest. Maybe they can include a post-processing step that can allow us to merge parts? That would be the simplest option right? Especially with enhanced parts coming up eventually.

Also the Freezed route isn't perfect. There are loads of bugs and unexpected warnings :)

Its still much better than the route we have now, which is extremely limited.

I do acknowledge that it's an experimental feature you basically just threw together, so its not a strong complaint as of right now, but its barely functional right now.

TekExplorer avatar Aug 28 '25 22:08 TekExplorer