0

In Dart (2.15.0), I'm trying to use jsonEncode with enums by defining a toJson method. And it's not working.

import 'dart:convert';

enum Day { monday, tuesday }

extension ParseToJsonString on Day {
  String toJson() {
    return this.toString().split('.').last;
  }
}

class Saturday {
  String toJson() => "WOOHOO Saturday";
}

main() {
  //works!
  Saturday s=Saturday();
  print(s.toJson());
  print(jsonEncode(s));
  
  Day m = Day.monday;
  print(m.toJson()); //prints 'monday'
  print(m); //prints Day.monday
  print(jsonEncode(m)); // Uncaught Error: Converting object to an encodable object failed: Instance of 'Day'
}

According to the docs, jsonEncode will look for the toJson() method.

And the extensions work when called directly on an enum, but somehow jsonEncode isn't finding the toJSON.

Dart How to get the "value" of an enum https://dart.dev/guides/language/extension-methods

Any idea if this is a bug or the expected behavior?

Otherwise, can I use enums and somehow define something to work with jsonEncode?

Thanks!

chongman
  • 2,447
  • 4
  • 21
  • 23
  • 1
    This is expected behavior since extensions is "static" and are resolved statically when compiling the programming and is therefore not part of the objects at runtime. This also means it only works if the analyzer can determine the specific type (so no `dynamic`). The article you links to have this segment which describes this: "The reason that `dynamic` doesn’t work is that extension methods are resolved against the static type of the receiver. Because extension methods are resolved statically, they’re as fast as calling a static function." – julemand101 Dec 08 '21 at 10:03
  • Thanks. I finally figured it out after some digging. One can make it work with a recast. – chongman Dec 08 '21 at 10:19

1 Answers1

1

I did some digging, and this is the correct behavior due to how jsonEncode works.

See https://github.com/dart-lang/sdk/issues/42742

Note, even using the optional parameter for jsonEncode doesn't fix it:

  print(jsonEncode(m, toEncodable: (x)=>x!.toJson()) ); // won't work.

To get past the "extensions don't work on dynamic types", we have to use a recast as well:

  print(jsonEncode(
    m,
    toEncodable: (x) {
      Day recastX = x as Day;
      return recastX.toJson();
    },
  )); // works, prints 'monday'

See it on dartpad

chongman
  • 2,447
  • 4
  • 21
  • 23