package org.stagemonitor.core.util; import com.codahale.metrics.json.MetricsModule; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.module.afterburner.AfterburnerModule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.TimeUnit; public class JsonUtils { private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class); private static final ObjectMapper MAPPER = new ObjectMapper(); static { if (Double.parseDouble(System.getProperty("java.specification.version")) > 1.6) { AfterburnerModuleRegisterer.registerAfterburnerModule(); } MAPPER.registerModule(new MetricsModule(TimeUnit.SECONDS, TimeUnit.MILLISECONDS, false)); MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); } private JsonUtils() { } public static boolean versionsMatch(Version v1, Version v2) { return v1.getMajorVersion() == v2.getMajorVersion() && v1.getMinorVersion() == v2.getMinorVersion() && v1.getPatchLevel() == v2.getPatchLevel(); } public static String toJson(Object o) { if (o == null) { return null; } try { return MAPPER.writeValueAsString(o); } catch (JsonProcessingException e) { logger.error(e.getMessage(), e); return null; } } public static String toJson(Object o, String exclude) { final ObjectNode jsonNode = MAPPER.valueToTree(o); jsonNode.remove(exclude); return jsonNode.toString(); } public static void writeJsonToOutputStream(Object o, OutputStream os) throws IOException { MAPPER.writeValue(os, o); } public static ObjectMapper getMapper() { return MAPPER; } public static ObjectNode toObjectNode(Object o) { return MAPPER.valueToTree(o); } public static <T> ObjectReader getObjectReader(Class<T> type) { final ObjectReader objectReader; if (getMapper().version().compareTo(new Version(2, 6, 0, null, "com.fasterxml.jackson.core", "jackson-databind")) >= 0) { objectReader = getMapper().readerFor(type); } else { objectReader = getMapper().reader(type); } return objectReader; } private static class AfterburnerModuleRegisterer { private static void registerAfterburnerModule() { /* * Avoiding java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.ser.BeanPropertyWriter.isUnwrapping() * This happens, if the version of jackson databind less that the Afterburner version. * * One reason can be maven, because it resolves a version conflict with the nearest-wins strategy it is possible that * jackson-module-afterburner is in a higher version that jackson-databind and jackson-core * * Another reason could be that a application server bundled version of jackson databind is used */ final AfterburnerModule afterburnerModule = new AfterburnerModule(); if (versionsMatch(MAPPER.version(), afterburnerModule.version())) { MAPPER.registerModule(afterburnerModule); } } } }