散列json并在Java中进行比较

时间:2019-05-28 10:07:10

标签: java json

我正在做一些迁移,我想比较在新旧服务上发送的JSON请求。我的JSON中有一些敏感数据,所以我不想直接记录它,我想先哈希然后记录它。一旦散列,我想比较散列。

PS:我有复杂的JSON字符串

{'method': 'do.stuff', 'params': ['asdf', 3, {'foo': 'bar'}]}

{'params': ['asdf', 3, {'foo': 'bar'}], 'method': 'do.stuff'}

无论顺序如何,都应返回相同的哈希值

1 个答案:

答案 0 :(得分:0)

一种执行此操作的方法是对每个对象的键进行排序,以使JSON具有相同的顺序,然后创建一个哈希。您还需要注意嵌套对象和数组。

例如...

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.DigestUtils;

import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class JsonHash {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        String jsonStringA = "{\"a\": \"100\", \"b\": \"200\", \"c\": [{\"d\": 200, \"e\": 100}], \"p\": null}";
        String jsonStringB = "{\"p\": null, \"b\": \"200\", \"a\": \"100\", \"c\": [{\"e\": 100, \"d\": 200}]}";
        String jsonStringC = "{\"p\": 1, \"b\": \"200\", \"a\": \"100\", \"c\": [{\"e\": 100, \"d\": 200}]}";

        String hashA = getHash(mapper, jsonStringA);
        String hashB = getHash(mapper, jsonStringB);
        String hashC = getHash(mapper, jsonStringC);

        System.out.println(hashA);
        System.out.println(hashB);
        System.out.println(hashC);
    }

    private static String getHash(ObjectMapper mapper, String jsonStringA) throws IOException {
        JsonNode jsonNode = mapper.readTree(jsonStringA);
        Map map = mapper.convertValue(jsonNode, Map.class);
        TreeMap sorted = sort(map);
        String s = mapper.writeValueAsString(sorted);
        byte[] md5Digest = DigestUtils.md5Digest(s.getBytes());
        return DatatypeConverter.printHexBinary(md5Digest).toUpperCase();
    }

    private static TreeMap sort(Map map) {
        TreeMap result = new TreeMap();
        map.forEach((k, v) -> {
            if(v != null) {
                if (v instanceof Map) {
                    result.put(k, sort((Map) v));
                } else if (v instanceof List) {
                    result.put(k, copyArray((List) v));
                } else {
                    result.put(k, v);
                }
            } else {
               result.put(k, null);
            }
        });
        return result;
    }

    private static List copyArray(List v) {
        List result = new ArrayList(v.size());

        for (int i = 0; i < v.size(); i++) {
            Object element = v.get(i);

            if(element != null) {
                if (element instanceof Map) {
                    result.add(sort((Map) element));
                } else if (element instanceof List) {
                    result.add(copyArray((List) element));
                } else {
                    result.add(element);
                }
            } else {
                result.add(null);
            }
        }

        return result;
    }
}

输出:

FADE525B0423415184D913299E90D959
FADE525B0423415184D913299E90D959
B49993CB657F1C9A62A339E5482F93D1

示例的哈希均为3EBAD6BDF5064304B3DD499BDAF0E635