Skip to content

Commit

Permalink
Fixed JSON mapper bug.
Browse files Browse the repository at this point in the history
Fixes #24
  • Loading branch information
morazow committed Oct 14, 2021
1 parent 7aecf88 commit 4c15658
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-build.yml
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
scala: [ 2.12.14, 2.13.6 ]
scala: [ 2.12.15, 2.13.6 ]

steps:
- name: Checkout the Repository
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Expand Up @@ -10,7 +10,7 @@ lazy val orgSettings = Seq(

lazy val buildSettings = Seq(
scalaVersion := "2.13.6",
crossScalaVersions := Seq("2.12.14", "2.13.6")
crossScalaVersions := Seq("2.12.15", "2.13.6")
)

lazy val root =
Expand Down
1 change: 1 addition & 0 deletions doc/changes/changelog.md
@@ -1,5 +1,6 @@
# Releases

* [0.3.1](changes_0.3.1.md)
* [0.3.0](changes_0.3.0.md)
* [0.2.0](changes_0.2.0.md)
* [0.1.0](changes_0.1.0.md)
20 changes: 20 additions & 0 deletions doc/changes/changes_0.3.1.md
@@ -0,0 +1,20 @@
# Import Export UDF Common Scala 0.3.1, released 2021-10-14

Code name: Fixed JSON Mapper

## Summary

This release fixes parsing bugs in JSON mapper functionality.

## Bug Fixes

* #24: Fixed JSON mapper issues

## Dependency Updates

### Runtime Dependency Updates

### Test Dependency Updates

### Plugin Updates

1 change: 1 addition & 0 deletions project/Dependencies.scala
Expand Up @@ -31,6 +31,7 @@ object Dependencies {
exclude ("org.scala-lang", "scala-reflect"),
"org.apache.avro" % "avro" % AvroVersion
exclude ("org.slf4j", "slf4j-api")
exclude ("org.apache.commons", "commons-compress")
excludeAll (
ExclusionRule(organization = "com.fasterxml.jackson.core"),
ExclusionRule(organization = "com.fasterxml.jackson.module")
Expand Down
61 changes: 54 additions & 7 deletions src/main/scala/com/exasol/common/json/JsonMapper.scala
@@ -1,20 +1,67 @@
package com.exasol.common.json

import com.fasterxml.jackson.core.`type`.TypeReference
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.MapperFeature
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.json.{JsonMapper => BaseJsonMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.ClassTagExtensions

/**
* JSON parsing helper object class.
*/
object JsonMapper {

private[this] val mapper = BaseJsonMapper
.builder()
.addModule(DefaultScalaModule)
.build()
private[this] class ScalaJsonMapper(jsonMapper: BaseJsonMapper)
extends BaseJsonMapper(jsonMapper)
with ClassTagExtensions

private[this] val mapper = {
val builder = BaseJsonMapper
.builder()
.findAndAddModules()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
.enable(JsonParser.Feature.ALLOW_COMMENTS)
.defaultMergeable(true)
new ScalaJsonMapper(builder.build())
}

/**
* Parses given value type into a JSON string.
*
* For parsing into pretty indented JSON use {@link toPrettyJson}.
*
* @param value a provided value type
* @return JSON string
*/
def toJson[T](value: T): String =
mapper.writeValueAsString(value)

/**
* Parses given value into pretty JSON format.
*
* @param value a provided value type
* @return pretty JSON string
*/
def toPrettyJson[T](value: T): String =
mapper.writer(SerializationFeature.INDENT_OUTPUT).writeValueAsString(value)

/**
* Parses JSON string into a type.
*
* @param jsonString a JSON string
* @return parsed value
*/
def fromJson[T: Manifest](jsonString: String): T =
mapper.readValue[T](jsonString)

/**
* Parses JSON string into a type.
*
* @param jsonString a JSON string
* @return parsed value
*/
@deprecated("Use fromJson method instead.", "0.3.1")
def parseJson[T: Manifest](jsonString: String): T =
mapper.readValue[T](jsonString, new TypeReference[T]() {})
fromJson(jsonString)

}
29 changes: 27 additions & 2 deletions src/test/scala/com/exasol/common/json/JsonMapperTest.scala
@@ -1,14 +1,39 @@
package com.exasol.common.json

import java.util.LinkedHashMap

import com.fasterxml.jackson.databind.JsonNode

import org.scalatest.funsuite.AnyFunSuite

class JsonMapperTest extends AnyFunSuite {

test("parse to and from json to internal data type") {
test("parses to/from JSON to internal Scala data type") {
val jsonStr = """{"name":"John","age":30,"skills":["a","b","c"]}"""
val map = JsonMapper.parseJson[Map[String, Any]](jsonStr)
val map = JsonMapper.fromJson[Map[String, Any]](jsonStr)
assert(map.get("skills") === Option(Seq("a", "b", "c")))
assert(JsonMapper.toJson(map) === jsonStr)
}

test("parses to/from JSON to JsonNode") {
val jsonStr =
"""|{
| "number" : 1,
| "record" : {
| "field1" : "value1",
| "field2" : 23
| }
|}""".stripMargin
val jsonNode = JsonMapper.fromJson[JsonNode](jsonStr)
assert(JsonMapper.toPrettyJson(jsonNode) === jsonStr)
}

test("parses to/from JSON to Java LinkedHashMap") {
val jsonStr = """{"name":"John","age":"ten"}"""
val expected = new LinkedHashMap[String, String](java.util.Map.of("name", "John", "age", "ten"))
val parsedMap = JsonMapper.fromJson[LinkedHashMap[String, String]](jsonStr)
assert(parsedMap === expected)
assert(JsonMapper.toJson(parsedMap) === jsonStr)
}

}

0 comments on commit 4c15658

Please sign in to comment.