我正在做一些迁移,我想比较在新旧服务上发送的JSON请求。我的JSON中有一些敏感数据,所以我不想直接记录它,我想先哈希然后记录它。一旦散列,我想比较散列。
PS:我有复杂的JSON字符串
{'method': 'do.stuff', 'params': ['asdf', 3, {'foo': 'bar'}]}
和
{'params': ['asdf', 3, {'foo': 'bar'}], 'method': 'do.stuff'}
无论顺序如何,都应返回相同的哈希值
答案 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