Skip to content

Commit 074c425

Browse files
authored
#24: Fixed JSON mapper bug. (#25)
Fixes #24
1 parent 7aecf88 commit 074c425

File tree

7 files changed

+105
-11
lines changed

7 files changed

+105
-11
lines changed

.github/workflows/ci-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
fail-fast: false
1212
matrix:
13-
scala: [ 2.12.14, 2.13.6 ]
13+
scala: [ 2.12.15, 2.13.6 ]
1414

1515
steps:
1616
- name: Checkout the Repository

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ lazy val orgSettings = Seq(
1010

1111
lazy val buildSettings = Seq(
1212
scalaVersion := "2.13.6",
13-
crossScalaVersions := Seq("2.12.14", "2.13.6")
13+
crossScalaVersions := Seq("2.12.15", "2.13.6")
1414
)
1515

1616
lazy val root =

doc/changes/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Releases
22

3+
* [0.3.1](changes_0.3.1.md)
34
* [0.3.0](changes_0.3.0.md)
45
* [0.2.0](changes_0.2.0.md)
56
* [0.1.0](changes_0.1.0.md)

doc/changes/changes_0.3.1.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Import Export UDF Common Scala 0.3.1, released 2021-10-14
2+
3+
Code name: Fixed JSON Mapper
4+
5+
## Summary
6+
7+
This release fixes parsing bugs in JSON mapper functionality.
8+
9+
## Bug Fixes
10+
11+
* #24: Fixed JSON mapper issues
12+
13+
## Dependency Updates
14+
15+
### Runtime Dependency Updates
16+
17+
### Test Dependency Updates
18+
19+
### Plugin Updates
20+

project/Dependencies.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ object Dependencies {
3131
exclude ("org.scala-lang", "scala-reflect"),
3232
"org.apache.avro" % "avro" % AvroVersion
3333
exclude ("org.slf4j", "slf4j-api")
34+
exclude ("org.apache.commons", "commons-compress")
3435
excludeAll (
3536
ExclusionRule(organization = "com.fasterxml.jackson.core"),
3637
ExclusionRule(organization = "com.fasterxml.jackson.module")
Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,67 @@
11
package com.exasol.common.json
22

3-
import com.fasterxml.jackson.core.`type`.TypeReference
3+
import com.fasterxml.jackson.core.JsonParser
4+
import com.fasterxml.jackson.databind.MapperFeature
5+
import com.fasterxml.jackson.databind.SerializationFeature
46
import com.fasterxml.jackson.databind.json.{JsonMapper => BaseJsonMapper}
5-
import com.fasterxml.jackson.module.scala.DefaultScalaModule
7+
import com.fasterxml.jackson.module.scala.ClassTagExtensions
68

9+
/**
10+
* JSON parsing helper object class.
11+
*/
712
object JsonMapper {
813

9-
private[this] val mapper = BaseJsonMapper
10-
.builder()
11-
.addModule(DefaultScalaModule)
12-
.build()
14+
private[this] class ScalaJsonMapper(jsonMapper: BaseJsonMapper)
15+
extends BaseJsonMapper(jsonMapper)
16+
with ClassTagExtensions
1317

18+
private[this] val mapper = {
19+
val builder = BaseJsonMapper
20+
.builder()
21+
.findAndAddModules()
22+
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
23+
.enable(JsonParser.Feature.ALLOW_COMMENTS)
24+
.defaultMergeable(true)
25+
new ScalaJsonMapper(builder.build())
26+
}
27+
28+
/**
29+
* Parses given value type into a JSON string.
30+
*
31+
* For parsing into pretty indented JSON use {@link toPrettyJson}.
32+
*
33+
* @param value a provided value type
34+
* @return JSON string
35+
*/
1436
def toJson[T](value: T): String =
1537
mapper.writeValueAsString(value)
1638

39+
/**
40+
* Parses given value into pretty JSON format.
41+
*
42+
* @param value a provided value type
43+
* @return pretty JSON string
44+
*/
45+
def toPrettyJson[T](value: T): String =
46+
mapper.writer(SerializationFeature.INDENT_OUTPUT).writeValueAsString(value)
47+
48+
/**
49+
* Parses JSON string into a type.
50+
*
51+
* @param jsonString a JSON string
52+
* @return parsed value
53+
*/
54+
def fromJson[T: Manifest](jsonString: String): T =
55+
mapper.readValue[T](jsonString)
56+
57+
/**
58+
* Parses JSON string into a type.
59+
*
60+
* @param jsonString a JSON string
61+
* @return parsed value
62+
*/
63+
@deprecated("Use fromJson method instead.", "0.3.1")
1764
def parseJson[T: Manifest](jsonString: String): T =
18-
mapper.readValue[T](jsonString, new TypeReference[T]() {})
65+
fromJson(jsonString)
1966

2067
}
Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,39 @@
11
package com.exasol.common.json
22

3+
import java.util.LinkedHashMap
4+
5+
import com.fasterxml.jackson.databind.JsonNode
6+
37
import org.scalatest.funsuite.AnyFunSuite
48

59
class JsonMapperTest extends AnyFunSuite {
610

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

18+
test("parses to/from JSON to JsonNode") {
19+
val jsonStr =
20+
"""|{
21+
| "number" : 1,
22+
| "record" : {
23+
| "field1" : "value1",
24+
| "field2" : 23
25+
| }
26+
|}""".stripMargin
27+
val jsonNode = JsonMapper.fromJson[JsonNode](jsonStr)
28+
assert(JsonMapper.toPrettyJson(jsonNode) === jsonStr)
29+
}
30+
31+
test("parses to/from JSON to Java LinkedHashMap") {
32+
val jsonStr = """{"name":"John","age":"ten"}"""
33+
val expected = new LinkedHashMap[String, String](java.util.Map.of("name", "John", "age", "ten"))
34+
val parsedMap = JsonMapper.fromJson[LinkedHashMap[String, String]](jsonStr)
35+
assert(parsedMap === expected)
36+
assert(JsonMapper.toJson(parsedMap) === jsonStr)
37+
}
38+
1439
}

0 commit comments

Comments
 (0)