【问题标题】: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&lt;String, dynamic&gt;' is not a subtype of type 'Map&lt;String, String&gt;')。好的,我知道如果我不强制转换它,那么 paradigms 无论如何都会是那种奇怪的类型,但是我无法将它传递给某个类,这意味着我必须制作类型这些成员也是动态的,而且看起来有点丑(我已经测试过了,它有效)。难道没有办法从jsonDecode 中简单地得到Map 吗?我认为这就是它应该如何工作的方式?

【问题讨论】:

    标签: json dart


    【解决方案1】:

    JSON解析的静态返回类型为dynamic,因为它可以是map、list、number、string、boolean或null。出于同样的原因,如果它是一个地图,它就是一个Map&lt;String, dynamic&gt;,因为值可以是上述任何一个。

    在您的情况下,您碰巧知道结果始终是一个映射,并且该映射的值又是映射,并且这些映射的值都是字符串。因此,数据将匹配 Map&lt;String, Map&lt;String, String&gt;&gt;,但 JSON 解码器不会提前知道这一点,因此它会构建一个包含 Map&lt;String, dynamic&gt; 值的 Map&lt;String, dynamic&gt;

    Dart 将泛型类型具体化,因此仅包含字符串的Map&lt;String, dynamic&gt;Map&lt;String, String&gt; 不同。您可以为前者添加一个数字值,而不是为后者添加一个数字值,因此它们是不同的。

    要将您的数据映射转换为 Map&lt;String, String&gt; 类型的东西,您可以急切地这样做:

    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 中。你说&lt;String, String&gt;,其实只能是&lt;String, dynamic&gt;。改变 Map&lt;String, Map&lt;String, dynamic&gt;&gt; 会解决你的问题。

      此外,正如您在链接的答案中看到的那样,完全不需要使用 from 构造函数来创建新的 Map,因为 jsonDecode 已经返回了您尝试创建的确切数据类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-24
        • 2014-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-29
        • 2016-07-21
        • 2015-11-21
        相关资源
        最近更新 更多