Я делаю некоторую миграцию и хотел бы сравнить запросы JSON, отправляемые на новую и старую службу. У меня есть некоторые конфиденциальные данные в моем JSON, поэтому я не хочу регистрировать их напрямую, я хочу хэшировать, а затем регистрировать их. После хеширования я хочу сравнить хэши.
PS: у меня есть сложные строки JSON
{'method': 'do.stuff', 'params': ['asdf', 3, {'foo': 'bar'}]}
а также
{'params': ['asdf', 3, {'foo': 'bar'}], 'method': 'do.stuff'}
Должен возвращать один и тот же хеш независимо от порядка
Один из способов сделать это — отсортировать ключи каждого объекта, чтобы 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.