11package io .yannick_cw .sjq
22
3+ import cats .instances .map .catsKernelStdMonoidForMap
4+ import cats .instances .int .catsKernelStdGroupForInt
5+ import cats .syntax .foldable ._
6+ import cats .instances .list ._
7+ import cats .kernel .Semigroup
38import io .circe .Json
4- import cats .implicits ._
59
610object jsonToCaseClass {
711 case class CC (name : String , content : Map [String , String ])
@@ -17,13 +21,12 @@ object jsonToCaseClass {
1721 private def renderCC (cc : CC ): String =
1822 s " case class ${cc.name}( ${cc.content.map { case (key, value) => s " $key: $value" }.mkString(" , " )}) "
1923
20- private def buildCC (j : Json , nextLevelName : String , doneCCs : List [CC ]): (String , List [CC ]) = {
24+ private def buildCC (j : Json , nextLevelName : String , doneCCs : List [CC ]): (Option [ String ] , List [CC ]) = {
2125 j.fold(
22- // todo decode not at all if null
23- " Option[String]" -> doneCCs,
24- _ => " Boolean" -> doneCCs,
25- _ => " Double" -> doneCCs,
26- _ => " String" -> doneCCs,
26+ Some (" Null" ) -> doneCCs,
27+ _ => Some (" Boolean" ) -> doneCCs,
28+ _ => Some (" Double" ) -> doneCCs,
29+ _ => Some (" String" ) -> doneCCs,
2730 array =>
2831 array.toList match {
2932 case all @ ele :: rest if all.forall(_.isObject) =>
@@ -32,15 +35,16 @@ object jsonToCaseClass {
3235 case ((newValueName, aggCCs), nextJson) =>
3336 newValueName -> buildCC(nextJson, nextLevelName, aggCCs)._2
3437 }
35-
3638 val (valueName, ccs) = innerType match {
37- case (valueName, Nil ) => valueName -> doneCCs
38- case (valueName, ele :: Nil ) => valueName -> (ele :: Nil )
39- case (valueName, ele :: more) =>
39+ case (Some ( valueName) , Nil ) => valueName -> doneCCs
40+ case (Some ( valueName) , ele :: Nil ) => valueName -> (ele :: Nil )
41+ case (Some ( valueName) , ele :: more) =>
4042 val (nextLevelCCs, otherCCs) = (ele :: more)
4143 .partition(_.name.startsWith(valueName))
4244
43- val allContent = nextLevelCCs.map(_.content).fold(Map .empty)(_ ++ _)
45+ implicit val sSemi : Semigroup [String ] =
46+ (x : String , y : String ) => if (x == " Null" ) s " Option[ $y] " else if (y == " Null" ) s " Option[ $x] " else x
47+ val allContent = nextLevelCCs.map(_.content).combineAll
4448 val keyCountPerContent =
4549 nextLevelCCs.map(cc => cc.content.map[String , Int ] { case (key, _) => (key, 1 ) }).combineAll
4650
@@ -51,22 +55,23 @@ object jsonToCaseClass {
5155 case (key, _) => key -> s " Option[ ${allContent(key)}] "
5256 }))
5357 valueName -> (newCC :: otherCCs)
58+ case _ => " " -> doneCCs
5459 }
5560
56- s " List[ $valueName] " -> ccs
61+ Some ( s " List[ $valueName] " ) -> ccs
5762 case ele :: rest if rest.forall(_ == ele) =>
5863 val (newValue, allCCs) = buildCC(ele, nextLevelName, doneCCs)
59- s " List[ $newValue ] " -> allCCs
60- case _ => " List[String]" -> doneCCs
64+ newValue.map(v => s " List[ $v ] " ) -> allCCs
65+ case _ => Some ( " List[String]" ) -> doneCCs
6166 },
6267 jObj => {
6368 val (allNewCCs, newCC) = jObj.toMap.foldLeft(doneCCs -> CC (nextLevelName, Map .empty)) {
6469 case ((allCCs, currCC), (key, value)) =>
6570 val safeNextLevelName = findFreeName(currCC :: allCCs, key)
6671 val (newValue, allNewCCs) = buildCC(value, safeNextLevelName, allCCs)
67- ( allNewCCs, currCC.copy(content = currCC.content.updated(key, newValue)) )
72+ allNewCCs -> newValue.map(v => currCC.copy(content = currCC.content.updated(key, v))).getOrElse(currCC )
6873 }
69- (nextLevelName, newCC :: allNewCCs)
74+ (Some ( nextLevelName) , newCC :: allNewCCs)
7075 }
7176 )
7277 }
0 commit comments