8

以下代码打印:

false
false
true
{{a: b}, {a: b}}

代码

import "dart:json" as JSON;

main() {
  print(JSON.parse('{ "a" : "b" }') == JSON.parse('{ "a" : "b" }'));
  print({ "a" : "b" } == { "a" : "b" });
  print({ "a" : "b" }.toString() == { "a" : "b" }.toString());
  Set s = new Set();
  s.add(JSON.parse('{ "a" : "b" }'));
  s.add(JSON.parse('{ "a" : "b" }'));
  print(s);
}

我正在使用 json 并解析两个等效对象,将它们存储在一个 Set 中,希望它们不会被重复。情况并非如此,似乎是因为前两行(出乎意料?)导致错误。假设每个对象都是 JSON.parse() 的结果,那么正确比较两个 Map 对象的有效方法是什么?

4

4 回答 4

8

比较JSON 映射或列表(可能是嵌套的)是否相等的推荐方法是使用以下包中的 Equality 类

import 'package:collection/collection.dart';

例如,

Function eq = const DeepCollectionEquality().equals;
var json1 = JSON.parse('{ "a" : 1, "b" : 2 }');
var json2 = JSON.parse('{ "b" : 2, "a" : 1 }');
print(eq(json1, json2)); // => true

有关详细信息,请参阅此答案,其中讨论了一些不同的平等类:如何比较 Dart 中的平等列表?.

于 2014-03-13T14:35:27.343 回答
3

这是一个困难的问题,因为 JSON 对象只是 num、String、bool 和 Null 的列表和映射。在 Dart 中测试地图和列表是否相等仍然是一个问题,请参阅https://code.google.com/p/dart/issues/detail?id=2217

更新

此答案不再有效,请参阅答案@Patrice_Chalin

于 2013-08-19T20:40:01.507 回答
2

这实际上非常困难,因为 Maps 和 Lists 上的 == 运算符并没有真正将键/值/元素相互比较。

根据您的用例,您可能必须编写实用程序方法。我曾经写过这个又快又脏的函数:

bool mapsEqual(Map m1, Map m2) {
    Iterable k1 = m1.keys;
    Iterable k2 = m2.keys;
    // Compare m1 to m2
    if(k1.length!=k2.length) return false;
    for(dynamic o in k1) {
        if(!k2.contains(o)) return false;
        if(m1[o] is Map) {
            if(!(m2[o] is Map)) return false;
            if(!mapsEqual(m1[o], m2[o])) return false;
        } else {
            if(m1[o] != m2[o]) return false;
        }
    }
    return true;
}

请注意,虽然它处理嵌套的 JSON 对象,但它总是会false在涉及嵌套列表时立即返回。如果您想使用这种方法,您可能需要添加代码来处理它。

我曾经开始的另一种方法是为 Map 和 List 编写包装器(实现 Map/List 以正常使用它)并覆盖operator==,然后使用JsonParser和 JsonListener 使用这些包装器解析 JSON 字符串。由于我很快就放弃了它,我没有它的代码,也不知道它是否真的有效,但它可能值得一试。

于 2013-08-19T21:26:24.217 回答
0

来自 unittest 的匹配器库将执行此操作。

于 2013-08-20T19:07:49.253 回答