Skip to content

Commit dc1956b

Browse files
committed
feat: enhance JSON conversion with support for case classes, add new tests, and update dependencies
- Improved `JsonConverter` to handle case classes and drop null values. - Added `JsonConversionSuite` for comprehensive JSON conversion tests. - Updated to Scala 3.7.0 and refined `scalacOptions`. - Introduced new imports and utilities for enhanced JSON handling.
1 parent 0144715 commit dc1956b

File tree

7 files changed

+115
-9
lines changed

7 files changed

+115
-9
lines changed

build.sbt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ developers := List(
2020

2121
licenses += ("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0.html"))
2222

23-
crossScalaVersions := Seq("3.6.4", "2.13.16")
23+
crossScalaVersions := Seq("3.7.0", "2.13.16")
2424

2525
scalaVersion := crossScalaVersions.value.head
2626

27-
scalacOptions += "-deprecation"
27+
scalacOptions ++= Seq("-deprecation")
28+
//scalacOptions ++= Seq("--Xmax-inlines", "128")
2829

2930
Test / parallelExecution := false
3031

src/main/scala/dev/mongocamp/driver/mongodb/jdbc/MongoJdbcConnection.scala

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
package dev.mongocamp.driver.mongodb.jdbc
22

3+
import com.mongodb.event.CommandListener
4+
import com.mongodb.event.ConnectionPoolListener
35
import dev.mongocamp.driver.mongodb.bson.BsonConverter
46
import dev.mongocamp.driver.mongodb.database.DatabaseProvider
7+
import dev.mongocamp.driver.mongodb.database.MongoConfig.DefaultApplicationName
8+
import dev.mongocamp.driver.mongodb.database.MongoConfig.DefaultAuthenticationDatabaseName
9+
import dev.mongocamp.driver.mongodb.database.MongoConfig.DefaultHost
10+
import dev.mongocamp.driver.mongodb.database.MongoConfig.DefaultPort
11+
import dev.mongocamp.driver.mongodb.database.MongoPoolOptions
512
import dev.mongocamp.driver.mongodb.jdbc.statement.MongoPreparedStatement
13+
import dev.mongocamp.driver.mongodb.json._
614
import dev.mongocamp.driver.mongodb.json.JsonConverter
715
import java.sql
816
import java.sql.Blob
@@ -22,6 +30,8 @@ import java.util
2230
import java.util.concurrent.Executor
2331
import java.util.Properties
2432
import org.mongodb.scala.bson.collection.immutable.Document
33+
import org.mongodb.scala.MongoClientSettings
34+
import org.mongodb.scala.ServerAddress
2535
import scala.jdk.CollectionConverters._
2636

2737
class MongoJdbcConnection(databaseProvider: DatabaseProvider) extends Connection with MongoJdbcCloseable {
@@ -234,11 +244,50 @@ class MongoJdbcConnection(databaseProvider: DatabaseProvider) extends Connection
234244
override def getClientInfo: Properties = {
235245
val properties = new Properties()
236246
properties.setProperty("ApplicationName", databaseProvider.config.applicationName)
237-
val document = Document(new JsonConverter().toJson(databaseProvider.config))
247+
case class MongoConfigHelper(
248+
database: String,
249+
host: String = DefaultHost,
250+
port: Int = DefaultPort,
251+
var applicationName: String = DefaultApplicationName,
252+
userName: Option[String] = None,
253+
password: Option[String] = None,
254+
authDatabase: String = DefaultAuthenticationDatabaseName,
255+
poolOptions: MongoPoolOptions = MongoPoolOptions(),
256+
compressors: List[String] = List.empty,
257+
connectionPoolListener: List[String] = List.empty,
258+
commandListener: List[String] = List.empty,
259+
customClientSettings: Option[String] = None,
260+
serverAddressList: List[String] = List.empty
261+
)
262+
val logConfig = Option(databaseProvider.config)
263+
.map(
264+
c =>
265+
MongoConfigHelper(
266+
c.database,
267+
c.host,
268+
c.port,
269+
c.applicationName,
270+
c.userName,
271+
c.password,
272+
c.authDatabase,
273+
c.poolOptions,
274+
c.compressors,
275+
c.connectionPoolListener.map(_.toString),
276+
c.commandListener.map(_.toString),
277+
c.customClientSettings.map(_.toString),
278+
c.serverAddressList.map(_.toString)
279+
)
280+
)
281+
.get
282+
val document = Document(new JsonConverter().toJson(logConfig))
238283
BsonConverter
239284
.asMap(document)
240285
.foreach(
241-
entry => properties.setProperty(entry._1, entry._2.toString)
286+
entry => {
287+
if (entry._2 != null) {
288+
properties.setProperty(entry._1, entry._2.toString)
289+
}
290+
}
242291
)
243292
properties
244293
}

src/main/scala/dev/mongocamp/driver/mongodb/jdbc/statement/MongoPreparedStatement.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import dev.mongocamp.driver.mongodb.exception.SqlCommandNotSupportedException
55
import dev.mongocamp.driver.mongodb.jdbc.resultSet.MongoDbResultSet
66
import dev.mongocamp.driver.mongodb.jdbc.MongoJdbcCloseable
77
import dev.mongocamp.driver.mongodb.jdbc.MongoJdbcConnection
8+
import dev.mongocamp.driver.mongodb.json._
89
import dev.mongocamp.driver.mongodb.json.JsonConverter
910
import dev.mongocamp.driver.mongodb.sql.MongoSqlQueryHolder
1011
import dev.mongocamp.driver.mongodb.Converter
@@ -249,7 +250,8 @@ case class MongoPreparedStatement(connection: MongoJdbcConnection) extends Calla
249250
parameters.put(parameterIndex, s"'${t.toInstant.toString}'")
250251
case a: Array[Byte] =>
251252
parameters.put(parameterIndex, new JsonConverter().toJson(a))
252-
case a: Iterable[_] =>
253+
case a: Iterable[Any] =>
254+
import dev.mongocamp.driver.mongodb.json._
253255
parameters.put(parameterIndex, new JsonConverter().toJson(a))
254256
case _ =>
255257
parameters.put(parameterIndex, x.toString)

src/main/scala/dev/mongocamp/driver/mongodb/json/JsonConverter.scala

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
package dev.mongocamp.driver.mongodb.json
22

33
import better.files.Resource
4+
import com.typesafe.scalalogging.LazyLogging
45
import io.circe.jawn.decode
56
import io.circe.syntax._
67
import io.circe.Decoder
8+
import io.circe.Encoder
79

8-
class JsonConverter extends CirceSchema {
10+
class JsonConverter(dropNullValues: Boolean = false) extends CirceSchema with LazyLogging {
911

10-
def toJson(s: Any): String = {
11-
s.asJson.noSpaces
12+
def toJson[A <: Any](s: A)(implicit encoder: Encoder[A]): String = {
13+
if (dropNullValues) {
14+
s.asJson.deepDropNullValues.noSpaces
15+
}
16+
else {
17+
s.asJson.noSpaces
18+
}
1219
}
1320

1421
def readJsonMap(fileContent: String): Map[String, Any] = {
@@ -22,7 +29,11 @@ class JsonConverter extends CirceSchema {
2229
}
2330

2431
def toObject[A](jsonString: String)(implicit decoder: Decoder[A]): A = {
25-
decode[A](jsonString).getOrElse(null.asInstanceOf[A])
32+
val decodeResponse = decode[A](jsonString)
33+
if (decodeResponse.isLeft) {
34+
logger.warn(s"Error while decoding json: ${decodeResponse.left.get}")
35+
}
36+
decodeResponse.getOrElse(null.asInstanceOf[A])
2637
}
2738

2839
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package dev.mongocamp.driver.mongodb
2+
import io.circe.generic.AutoDerivation
3+
4+
package object json extends CirceSchema with AutoDerivation {}

src/main/scala/dev/mongocamp/driver/mongodb/schema/JsonSchema.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.mongocamp.driver.mongodb.schema
22

3+
import dev.mongocamp.driver.mongodb.json._
34
import dev.mongocamp.driver.mongodb.json.JsonConverter
45

56
case class JsonSchema(`$schema`: String, `$ref`: String, definitions: Map[String, JsonSchemaDefinition]) {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package dev.mongocamp.driver.mongodb.json
2+
3+
case class HelloWorld(greetings: String, name: String)
4+
case class HelloWorld2(greetings: String, name: String, option: Option[HelloWorld], subClass: List[Long])
5+
6+
class JsonConversionSuite extends munit.FunSuite {
7+
protected lazy val jsonConverter = new JsonConverter()
8+
9+
test("Convert to List to Json") {
10+
assertEquals(jsonConverter.toJson(Array(1, 2)), "[1,2]")
11+
assertEquals(jsonConverter.toJson(List[Int]()), "[]")
12+
assertEquals(jsonConverter.toJson(List("hallo", "Welt")), "[\"hallo\",\"Welt\"]")
13+
assertEquals(jsonConverter.toJson(List(1, 2)), "[1,2]")
14+
assertEquals(jsonConverter.toJson(Array.empty[String]), "[]")
15+
assertEquals(jsonConverter.toJson(Array("hallo", "Welt")), "[\"hallo\",\"Welt\"]")
16+
}
17+
18+
test("Convert Case Class to Json") {
19+
assertEquals(jsonConverter.toJson(HelloWorld("hello", "world")), "{\"greetings\":\"hello\",\"name\":\"world\"}")
20+
assertEquals(jsonConverter.toJson(HelloWorld("servus", "welt")), "{\"greetings\":\"servus\",\"name\":\"welt\"}")
21+
val jString: String = jsonConverter.toJson(HelloWorld2("servus", "welt", Option(HelloWorld("hello", "world")), List(1, 2, 3, 4, 5)))
22+
assertEquals(jString, "{\"greetings\":\"servus\",\"name\":\"welt\",\"option\":{\"greetings\":\"hello\",\"name\":\"world\"},\"subClass\":[1,2,3,4,5]}")
23+
val jString2: String = jsonConverter.toJson(HelloWorld2("servus", "welt", None, List.empty))
24+
assertEquals(jString2, "{\"greetings\":\"servus\",\"name\":\"welt\",\"option\":null,\"subClass\":[]}")
25+
}
26+
27+
test("Convert to Json to List") {
28+
assertEquals(jsonConverter.toObject[List[String]]("[]"), List())
29+
assertEquals(jsonConverter.toObject[List[String]]("[\"hallo\",\"Welt\"]"), List("hallo", "Welt"))
30+
assertEquals(jsonConverter.toObject[List[Int]]("[1,2]"), List(1, 2))
31+
assertEquals(jsonConverter.toObject[Array[String]]("[\"hallo\",\"Welt\"]").last, Array("hallo", "Welt").last)
32+
assertEquals(jsonConverter.toObject[Array[Int]]("[1,2]").last, Array(1, 2).last)
33+
}
34+
35+
test("Convert Json to Case Class") {
36+
assertEquals(jsonConverter.toObject[HelloWorld]("{\"name\":\"world\", \"greetings\":\"hello\"}"), HelloWorld("hello", "world"))
37+
}
38+
}

0 commit comments

Comments
 (0)