jsonEncode 不适用于枚举扩展;有解决方法吗?
Posted
技术标签:
【中文标题】jsonEncode 不适用于枚举扩展;有解决方法吗?【英文标题】:jsonEncode doesn't work with enum extensions; is there a workaround? 【发布时间】:2022-01-13 06:48:19 【问题描述】:在 Dart (2.15.0) 中,我试图通过定义一个 toJson 方法来使用带有枚举的 jsonEncode。而且它不起作用。
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'
根据docs,jsonEncode
会寻找toJson()
方法。
当直接在枚举上调用时,扩展工作正常,但不知何故 jsonEncode 找不到 toJSON。
Dart How to get the "value" of an enum https://dart.dev/guides/language/extension-methods
知道这是错误还是预期的行为?
否则,我可以使用枚举并以某种方式定义与 jsonEncode 一起使用的东西吗?
谢谢!
【问题讨论】:
这是预期行为,因为扩展是“静态的”,并且在编译程序时静态解析,因此在运行时不是对象的一部分。这也意味着它只有在分析器可以确定特定类型时才有效(所以没有dynamic
)。您链接到的文章有这样一段描述:“dynamic
不起作用的原因是扩展方法是针对接收器的静态类型解析的。因为扩展方法是静态解析的,所以它们的速度与调用静态函数。”
谢谢。经过一番挖掘,我终于弄明白了。可以通过重铸使其工作。
【参考方案1】:
我做了一些挖掘,由于 jsonEncode 的工作原理,这是正确的行为。
见https://github.com/dart-lang/sdk/issues/42742
注意,即使使用 jsonEncode 的可选参数也不能解决问题:
print(jsonEncode(m, toEncodable: (x)=>x!.toJson()) ); // won't work.
要克服“扩展不适用于动态类型”,我们还必须使用重铸:
print(jsonEncode(
m,
toEncodable: (x)
Day recastX = x as Day;
return recastX.toJson();
,
)); // works, prints 'monday'
查看dartpad
【讨论】:
以上是关于jsonEncode 不适用于枚举扩展;有解决方法吗?的主要内容,如果未能解决你的问题,请参考以下文章
ActionResult 扩展不适用于 Page() ActionResult 方法
在 Swift 中将 JSONEncoder 用于 Equatable 方法
React 建议和自动完成不适用于 VSCode 中带有 js 扩展名的文件