为啥 jsonDecode 返回一个不可转换为 Map<String, Map<String, String>> 的值?
Posted
技术标签:
【中文标题】为啥 jsonDecode 返回一个不可转换为 Map<String, Map<String, String>> 的值?【英文标题】:Why does jsonDecode return a value that is uncastable to Map<String, Map<String, String>>?为什么 jsonDecode 返回一个不可转换为 Map<String, Map<String, String>> 的值? 【发布时间】:2020-11-12 02:09:22 【问题描述】:我正在编写一个语言工具。我有一个看起来像这样的languages.json
文件:
"paradigms":
"test paradigm":
"1sg": "me",
"2sg.gen": "lo",
"3pl.acc": "tven"
(或者,至少这是相关部分)
然后,在我的主要 dart 文件中,我尝试打开 JSON 文件的一部分并将其解析为地图:
void main() async
var langjson = jsonDecode(await File('resource/languages.json').readAsString());
var paradigms = Map<String, Map<String, String>>.from(langjson['paradigms']);
现在飞镖告诉我_TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<String, String>')
。好的,我知道如果我不强制转换它,那么 paradigms
无论如何都会是那种奇怪的类型,但是我无法将它传递给某个类,这意味着我必须制作类型这些成员也是动态的,而且看起来有点丑(我已经测试过了,它有效)。难道没有办法从jsonDecode
中简单地得到Map
吗?我认为这就是它应该如何工作的方式?
【问题讨论】:
【参考方案1】:JSON解析的静态返回类型为dynamic
,因为它可以是map、list、number、string、boolean或null
。出于同样的原因,如果它是一个地图,它就是一个Map<String, dynamic>
,因为值可以是上述任何一个。
在您的情况下,您碰巧知道结果始终是一个映射,并且该映射的值又是映射,并且这些映射的值都是字符串。因此,数据将匹配 Map<String, Map<String, String>>
,但 JSON 解码器不会提前知道这一点,因此它会构建一个包含 Map<String, dynamic>
值的 Map<String, dynamic>
。
Dart 将泛型类型具体化,因此仅包含字符串的Map<String, dynamic>
与Map<String, String>
不同。您可以为前者添加一个数字值,而不是为后者添加一个数字值,因此它们是不同的。
要将您的数据映射转换为 Map<String, String>
类型的东西,您可以急切地这样做:
var paradigms = langJson["paradigms"].map(value: (k, v) => MapEntry(k, v as String));
或懒惰:
var paradigms = langJson["paradigms"].cast<String, String>();
前者立即检查所有值,并创建一个新的地图对象。后者包装原始地图对象,并在每次访问时检查该值是否为String
。
【讨论】:
【参考方案2】:_InternalLinkedHashMap
是Map
的子类型,您可以在此答案here 中阅读。您的代码的问题是您指定不兼容的值存储在Map
中。你说<String, String>
,其实只能是<String, dynamic>
。改变
Map<String, Map<String, dynamic>>
会解决你的问题。
此外,正如您在链接的答案中看到的那样,完全不需要使用 from
构造函数来创建新的 Map
,因为 jsonDecode
已经返回了您尝试创建的确切数据类型。
【讨论】:
以上是关于为啥 jsonDecode 返回一个不可转换为 Map<String, Map<String, String>> 的值?的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用 JSONDecoder.decode 方法时没有调用 Decodable 的 init 方法?
为啥 JsonDecoder 在尝试解析邮递员网址但处理其他网址时出现错误?