JacksonHelper.kt

  1. package com.hexagontk.serialization.jackson

  2. import com.fasterxml.jackson.core.JsonFactory
  3. import com.fasterxml.jackson.core.json.JsonReadFeature.*
  4. import com.fasterxml.jackson.core.json.JsonWriteFeature.QUOTE_FIELD_NAMES
  5. import com.fasterxml.jackson.databind.*
  6. import com.fasterxml.jackson.databind.DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
  7. import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES
  8. import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
  9. import com.fasterxml.jackson.databind.MapperFeature.SORT_PROPERTIES_ALPHABETICALLY
  10. import com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS
  11. import com.fasterxml.jackson.databind.json.JsonMapper
  12. import com.fasterxml.jackson.databind.node.*

  13. object JacksonHelper {

  14.     fun mapNode(node: JsonNode): Any =
  15.         nodeToCollection(node) ?: error("Parsed content is 'null'")

  16.     internal fun nodeToCollection(node: JsonNode): Any? =
  17.         when (node) {

  18.             is ArrayNode -> node.toList().map { nodeToCollection(it) }
  19.             is ObjectNode -> {
  20.                 var map = emptyMap<String, Any?>()

  21.                 for (f in node.fields())
  22.                     map = map + (f.key to nodeToCollection(f.value))

  23.                 map
  24.             }

  25.             is TextNode -> node.textValue()
  26.             is BigIntegerNode -> node.bigIntegerValue()
  27.             is BooleanNode -> node.booleanValue()
  28.             is DecimalNode -> node.doubleValue()
  29.             is DoubleNode -> node.doubleValue()
  30.             is FloatNode -> node.floatValue()
  31.             is IntNode -> node.intValue()
  32.             is LongNode -> node.longValue()
  33.             is NullNode -> null
  34.             is BinaryNode -> node.binaryValue()

  35.             else -> error("Unknown node type: ${node::class.qualifiedName}")
  36.         }

  37.     internal fun createMapper(mapperFactory: JsonFactory): JsonMapper =
  38.         baseMapper(mapperFactory).build()

  39.     internal fun createRelaxedMapper(mapperFactory: JsonFactory): JsonMapper =
  40.         baseMapper(mapperFactory)
  41.             .configure(ALLOW_UNQUOTED_FIELD_NAMES, true)
  42.             .configure(ALLOW_JAVA_COMMENTS, true)
  43.             .configure(ALLOW_SINGLE_QUOTES, true)
  44.             .configure(ALLOW_TRAILING_COMMA, true)
  45.             .configure(ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true)
  46.             .configure(ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS, true)
  47.             .configure(ALLOW_UNESCAPED_CONTROL_CHARS, true)
  48.             .configure(QUOTE_FIELD_NAMES, false)
  49.             .build()

  50.     private fun baseMapper(mapperFactory: JsonFactory): JsonMapper.Builder =
  51.         JsonMapper.builder(mapperFactory)
  52.             .findAndAddModules()
  53.             .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
  54.             .configure(FAIL_ON_EMPTY_BEANS, false)
  55.             .configure(FAIL_ON_MISSING_CREATOR_PROPERTIES, false)
  56.             .configure(ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
  57.             .configure(SORT_PROPERTIES_ALPHABETICALLY, false)
  58. }