/** Pretty prints given JSON string, replacing passwords by {@code 'xxxxx'}. * @param json JSON code as String which should be formatted * @return <code>json</code> formatted */ public static String prettyPrintJsonStringSecure(String json) { try { ObjectMapper jsonParser = new ObjectMapper(); JsonNode jsonTree = jsonParser.readValue(json, JsonNode.class); secure(jsonTree); ObjectWriter writer = jsonParser.writerWithDefaultPrettyPrinter(); return writer.writeValueAsString(jsonTree); } catch (IOException e) { throw new RuntimeException(e); } }
/** * Works like {@link JsonUtils#prettyPrintJsonStringSecure(java.lang.String)} but returns the unparsed JSON string if the * formatting fails. * @param json the input json to format * @return the formatted json or in error cases the unformatted json */ //TODO rename public static String prettyPrintJsonStringSecureWithFallback(String json) { String result = json; try { ObjectMapper jsonParser = new ObjectMapper(); JsonNode jsonTree = jsonParser.readValue(json, JsonNode.class); secure(jsonTree); ObjectWriter writer = jsonParser.writerWithDefaultPrettyPrinter(); result = writer.writeValueAsString(jsonTree); } catch (IOException e) { result = json; } return result; }
/** Very simple way to "erase" passwords - * replaces all field values whose names contains {@code 'pass'} by {@code 'xxxxx'}. */ private static JsonNode secure(JsonNode node) { if (node.isObject()) { ObjectNode objectNode = (ObjectNode)node; Iterator<Map.Entry<String, JsonNode>> fields = node.fields(); while (fields.hasNext()) { Map.Entry<String, JsonNode> field = fields.next(); if (field.getValue().isTextual() && field.getKey().toLowerCase().contains("pass")) { objectNode.put(field.getKey(), "xxxxx"); } else { secure(field.getValue()); } } return objectNode; } else if (node.isArray()) { ArrayNode arrayNode = (ArrayNode)node; Iterator<JsonNode> elements = arrayNode.elements(); while (elements.hasNext()) { secure(elements.next()); } return arrayNode; } else { return node; } } }