Skip to content

Commit 68dad45

Browse files
author
Simon Siedler
committed
feat: add conversion for scala duration
1 parent b4c8898 commit 68dad45

1 file changed

Lines changed: 75 additions & 102 deletions

File tree

Lines changed: 75 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,141 @@
11
package dev.mongocamp.driver.mongodb.json
22

33
import dev.mongocamp.driver.mongodb.bson.BsonConverter
4-
import io.circe.Decoder
54
import io.circe.Decoder.Result
6-
import io.circe.Encoder
7-
import io.circe.HCursor
8-
import io.circe.Json
5+
import io.circe._
96
import java.util.Date
107
import org.bson.types.ObjectId
118
import org.joda.time.DateTime
129
import org.mongodb.scala.Document
10+
import scala.concurrent.duration.Duration
1311
import scala.jdk.CollectionConverters._
1412

1513
trait CirceSchema extends CirceProductSchema {
1614

17-
implicit lazy val DocumentOneFormat: Encoder[org.mongodb.scala.Document] with io.circe.Decoder[org.mongodb.scala.Document] =
18-
new io.circe.Encoder[org.mongodb.scala.Document] with io.circe.Decoder[org.mongodb.scala.Document] {
15+
implicit lazy val DocumentOneFormat: Encoder[org.mongodb.scala.Document] with Decoder[org.mongodb.scala.Document] =
16+
new Encoder[org.mongodb.scala.Document] with Decoder[org.mongodb.scala.Document] {
1917
override def apply(a: org.mongodb.scala.Document): Json = {
2018
encodeMapStringAny(BsonConverter.asMap(a))
2119
}
2220

2321
override def apply(c: HCursor): Result[org.mongodb.scala.Document] = {
2422
Decoder.decodeString
25-
.map(
26-
s => {
27-
val document = new org.mongodb.scala.Document(org.mongodb.scala.bson.BsonDocument(s))
28-
document
29-
}
30-
)
23+
.map(s => {
24+
val document = new org.mongodb.scala.Document(org.mongodb.scala.bson.BsonDocument(s))
25+
document
26+
})
3127
.apply(c)
3228
}
3329
}
3430

35-
implicit lazy val DocumentTowFormat: Encoder[org.bson.Document] with io.circe.Decoder[org.bson.Document] = new io.circe.Encoder[org.bson.Document]
36-
with io.circe.Decoder[org.bson.Document] {
37-
override def apply(a: org.bson.Document): Json = {
38-
val map = a
39-
.keySet()
40-
.asScala
41-
.map(
42-
key => {
31+
implicit lazy val DocumentTowFormat: Encoder[org.bson.Document] with Decoder[org.bson.Document] =
32+
new Encoder[org.bson.Document] with Decoder[org.bson.Document] {
33+
override def apply(a: org.bson.Document): Json = {
34+
val map = a
35+
.keySet()
36+
.asScala
37+
.map(key => {
4338
val value = a.get(key)
4439
(key, encodeAnyToJson(value))
45-
}
46-
)
47-
.toMap
48-
encodeMapStringAny(map)
49-
}
40+
})
41+
.toMap
42+
encodeMapStringAny(map)
43+
}
5044

51-
override def apply(c: HCursor): Result[org.bson.Document] = {
52-
Decoder
53-
.decodeMap[String, Any]
54-
.map(
55-
m => {
45+
override def apply(c: HCursor): Result[org.bson.Document] = {
46+
Decoder
47+
.decodeMap[String, Any]
48+
.map(m => {
5649
val document = new org.bson.Document(m.asJava)
5750
document
58-
}
59-
)
60-
.apply(c)
51+
})
52+
.apply(c)
53+
}
6154
}
62-
}
6355

64-
implicit val DateFormat: Encoder[Date] with io.circe.Decoder[Date] = new io.circe.Encoder[Date] with io.circe.Decoder[Date] {
56+
implicit val DateFormat: Encoder[Date] with Decoder[Date] = new Encoder[Date] with Decoder[Date] {
6557
override def apply(d: Date): Json = {
6658
Option(d)
67-
.map(
68-
date => Encoder.encodeString.apply(date.toInstant.toString)
69-
)
59+
.map(date => Encoder.encodeString.apply(date.toInstant.toString))
7060
.getOrElse(Json.Null)
7161
}
7262

7363
override def apply(c: HCursor): Result[Date] = {
7464
Decoder.decodeString
75-
.map(
76-
s => new DateTime(s).toDate
77-
)
65+
.map(s => new DateTime(s).toDate)
7866
.apply(c)
7967
}
8068
}
8169

82-
implicit val DateTimeFormat: Encoder[DateTime] with io.circe.Decoder[DateTime] = new io.circe.Encoder[DateTime] with io.circe.Decoder[DateTime] {
70+
implicit val DateTimeFormat: Encoder[DateTime] with Decoder[DateTime] = new Encoder[DateTime] with Decoder[DateTime] {
8371
override def apply(d: DateTime): Json = {
8472
Option(d)
85-
.map(
86-
date => Encoder.encodeString.apply(date.toInstant.toString)
87-
)
73+
.map(date => Encoder.encodeString.apply(date.toInstant.toString))
8874
.getOrElse(Json.Null)
8975
}
9076

9177
override def apply(c: HCursor): Result[DateTime] = {
9278
Decoder.decodeString
93-
.map(
94-
s => new DateTime(s)
95-
)
79+
.map(s => new DateTime(s))
9680
.apply(c)
9781
}
9882
}
9983

100-
implicit val ObjectIdFormat: Encoder[ObjectId] with io.circe.Decoder[ObjectId] = new io.circe.Encoder[ObjectId] with io.circe.Decoder[ObjectId] {
84+
implicit val ObjectIdFormat: Encoder[ObjectId] with Decoder[ObjectId] = new Encoder[ObjectId] with Decoder[ObjectId] {
10185
override def apply(o: ObjectId): Json = {
10286
Option(o)
103-
.map(
104-
o => Encoder.encodeString.apply(o.toHexString)
105-
)
87+
.map(o => Encoder.encodeString.apply(o.toHexString))
10688
.getOrElse(Json.Null)
10789
}
10890

10991
override def apply(c: HCursor): Result[ObjectId] = {
11092
Decoder.decodeString
111-
.map(
112-
s => new ObjectId(s)
113-
)
93+
.map(s => new ObjectId(s))
11494
.apply(c)
11595
}
11696
}
11797

118-
implicit val MapStringAnyFormat: Encoder[Map[String, Any]] with io.circe.Decoder[Map[String, Any]] = new io.circe.Encoder[Map[String, Any]]
119-
with io.circe.Decoder[Map[String, Any]] {
120-
override def apply(a: Map[String, Any]): Json = {
121-
encodeMapStringAny(a)
98+
implicit val DurationFormat: Encoder[Duration] with Decoder[Duration] = new Encoder[Duration] with Decoder[Duration] {
99+
override def apply(d: Duration): Json = {
100+
Option(d)
101+
.map(duration => Json.fromString(duration.toString))
102+
.getOrElse(Json.Null)
122103
}
123104

124-
override def apply(c: HCursor): Result[Map[String, Any]] = {
125-
Decoder.decodeMap[String, Any].apply(c)
105+
override def apply(c: HCursor): Result[Duration] = {
106+
Decoder.decodeString.emap(s =>
107+
scala.util.Try(Duration(s)).toEither.left.map(_.getMessage)
108+
).apply(c)
126109
}
127110
}
128111

129-
implicit val AnyFormat: Encoder[Any] with io.circe.Decoder[Any] = new io.circe.Encoder[Any] with io.circe.Decoder[Any] {
112+
implicit val MapStringAnyFormat: Encoder[Map[String, Any]] with Decoder[Map[String, Any]] =
113+
new Encoder[Map[String, Any]] with Decoder[Map[String, Any]] {
114+
override def apply(a: Map[String, Any]): Json = {
115+
encodeMapStringAny(a)
116+
}
117+
118+
override def apply(c: HCursor): Result[Map[String, Any]] = {
119+
Decoder.decodeMap[String, Any].apply(c)
120+
}
121+
}
130122

123+
implicit val AnyFormat: Encoder[Any] with Decoder[Any] = new Encoder[Any] with Decoder[Any] {
131124
override def apply(a: Any): Json = {
132125
encodeAnyToJson(a)
133126
}
134127

135128
override def apply(c: HCursor): Result[Any] = {
136129
Decoder.decodeJson
137-
.map(
138-
a => decodeFromJson(a)
139-
)
130+
.map(a => decodeFromJson(a))
140131
.apply(c)
141132
}
142-
143133
}
144134

145135
def encodeMapStringAny(a: Map[String, Any]): Json = {
146136
Json.obj(
147137
a.keySet
148-
.map(
149-
key => (key, encodeAnyToJson(a(key)))
150-
)
138+
.map(key => (key, encodeAnyToJson(a(key))))
151139
.toList: _*
152140
)
153141
}
@@ -159,8 +147,7 @@ trait CirceSchema extends CirceProductSchema {
159147
val long = value.toLong
160148
if (long.isDefined) {
161149
long.get
162-
}
163-
else {
150+
} else {
164151
value.toDouble
165152
}
166153
case a if a.isString =>
@@ -169,29 +156,23 @@ trait CirceSchema extends CirceProductSchema {
169156
try {
170157
val date = new DateTime(string)
171158
date
172-
}
173-
catch {
159+
} catch {
174160
case _: Exception => string
175161
}
176-
}
177-
else {
162+
} else {
178163
string
179164
}
180165
case a if a.isBoolean => a.asBoolean.getOrElse(false)
181166
case a if a.isArray =>
182-
a.asArray.get.toList.map(
183-
e => decodeFromJson(e)
184-
)
167+
a.asArray.get.toList.map(e => decodeFromJson(e))
185168
case a if a.isObject =>
186-
a.asObject.get.toMap.map(
187-
e => (e._1, decodeFromJson(e._2))
188-
)
169+
a.asObject.get.toMap.map(e => (e._1, decodeFromJson(e._2)))
189170
case a if a.isNull => null
190171
case _ => null
191172
}
192173
}
193174

194-
def encodeAnyToJson(a: Any, deepth: Int = 0): Json = {
175+
def encodeAnyToJson(a: Any, depth: Int = 0): Json = {
195176
a match {
196177
case s: String => Json.fromString(s)
197178
case b: Boolean => Json.fromBoolean(b)
@@ -203,50 +184,42 @@ trait CirceSchema extends CirceProductSchema {
203184
case f: Float => Json.fromFloatOrNull(f)
204185
case option: Option[_] =>
205186
option
206-
.map(
207-
e => encodeAnyToJson(e, deepth)
208-
)
187+
.map(e => encodeAnyToJson(e, depth))
209188
.getOrElse(Json.Null)
210189
case d: Date => Encoder.encodeString.apply(d.toInstant.toString)
211190
case d: DateTime => Encoder.encodeString.apply(d.toInstant.toString)
191+
case d: Duration => Json.fromString(d.toString)
212192
case o: ObjectId => Encoder.encodeString.apply(o.toHexString)
213193
case m: Map[String, _] => encodeMapStringAny(m)
214194
case seq: Seq[_] =>
215195
Json.arr(
216-
seq.map(
217-
e => encodeAnyToJson(e, deepth)
218-
): _*
196+
seq.map(e => encodeAnyToJson(e, depth)): _*
219197
)
220198
case set: Set[_] =>
221199
Json.arr(
222200
set
223-
.map(
224-
e => encodeAnyToJson(e, deepth)
225-
)
201+
.map(e => encodeAnyToJson(e, depth))
226202
.toList: _*
227203
)
228204
case product: Product =>
229205
val productElementKeys = productElementNames(product).toList
230206
val fieldMap = productElementKeys
231-
.map(
232-
key => {
233-
val index = productElementKeys.indexOf(key)
234-
(key, product.productElement(index))
235-
}
236-
)
207+
.map(key => {
208+
val index = productElementKeys.indexOf(key)
209+
(key, product.productElement(index))
210+
})
237211
.toMap
238212
encodeAnyToJson(fieldMap)
239213
case r: Document => encodeAnyToJson(r.toMap)
240214
case any: Any =>
241-
if (deepth < 256) {
242-
encodeAnyToJson(any, deepth + 1)
243-
}
244-
else {
215+
if (depth < 256) {
216+
encodeAnyToJson(any, depth + 1)
217+
} else {
245218
Json.Null
246219
}
247220
case _ =>
248221
Json.Null
249222
}
250223
}
251224

252-
}
225+
}

0 commit comments

Comments
 (0)