测试解析的json映射是否相等的好方法是什么?

use*_*952 6 dart

以下代码打印:

false
false
true
{{a: b}, {a: b}}
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

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

Pat*_*lin 6

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

import 'package:collection/collection.dart';
Run Code Online (Sandbox Code Playgroud)

例如,

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
Run Code Online (Sandbox Code Playgroud)

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


Mar*_*ioP 1

这实际上相当困难,因为映射和列表上的 == 运算符并没有真正相互比较键/值/元素。

根据您的用例,您可能需要编写一个实用方法。我曾经写过这个快速但肮脏的函数:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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