diff --git a/.gitignore b/.gitignore
index 9b5daf9..fbe1a0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@ target/
.vscode
.ammonite
.bsp
-*.iml
\ No newline at end of file
+*.iml
+.DS_Store
diff --git a/.mill-jvm-opts b/.mill-jvm-opts
new file mode 100644
index 0000000..aa011f6
--- /dev/null
+++ b/.mill-jvm-opts
@@ -0,0 +1 @@
+-Xss10m
diff --git a/AUTOCONFIG.md b/AUTOCONFIG.md
index 66fc217..eb9f64b 100644
--- a/AUTOCONFIG.md
+++ b/AUTOCONFIG.md
@@ -5,7 +5,7 @@ Rather than implementing `ToJson` and `FromJson` by hand, you can generate them
@@ -17,8 +17,8 @@ If you like you can even skip the declaration by mixing in `AutoToJson` or
## Modifying field names with annotations
@@ -28,7 +28,7 @@ You can change the name of a field being read to/from JSON using the `@JsonName`
@@ -39,7 +39,7 @@ If your case class has optional parameters then you can use their default values
@@ -52,6 +52,6 @@ By providing an instance of `NullPointerBehavior` in the scope of your `ToJson`
diff --git a/USERGUIDE.md b/USERGUIDE.md
index 9226b52..7157b98 100644
--- a/USERGUIDE.md
+++ b/USERGUIDE.md
@@ -21,7 +21,7 @@
@@ -29,7 +29,7 @@
@@ -38,7 +38,7 @@
@@ -48,7 +48,7 @@
@@ -60,7 +60,7 @@ You can use ninny's dynamic update syntax easly to replace values way down in th
@@ -69,7 +69,7 @@ You can use ninny's dynamic update syntax easly to replace values way down in th
@@ -78,7 +78,7 @@ You can use ninny's dynamic update syntax easly to replace values way down in th
@@ -90,7 +90,7 @@ automatically using
diff --git a/build.sc b/build.sc
index 2e13b74..4a0587d 100644
--- a/build.sc
+++ b/build.sc
@@ -9,7 +9,7 @@ import $file.forProductN
val `2.12` = "2.12.15"
val `2.13` = "2.13.10"
-val `3` = "3.1.0"
+val `3` = "3.3.4"
val scalaTest = ivy"org.scalatest::scalatest:3.2.10"
val json4sVersion = Map(4 -> "4.0.6", 3 -> "3.6.12")
@@ -47,9 +47,13 @@ class Ninny(val crossScalaVersion: String)
"-feature",
"-unchecked",
"-deprecation"
- ) ++ (if (crossScalaVersion != `3`)
- Seq("-Ywarn-macros:after", "-Ywarn-unused")
- else None)
+ ) ++ (
+ if (crossScalaVersion != `3`) Seq("-Ywarn-macros:after", "-Ywarn-unused")
+ else None
+ ) ++ (
+ if (crossScalaVersion == `2.12`) Seq("-language:higherKinds")
+ else None
+ )
def ivyDeps =
Agg(
diff --git a/ninny/src-3/nrktkt/ninny/Annotation.scala b/ninny/src-3/nrktkt/ninny/Annotation.scala
new file mode 100644
index 0000000..bfa62bb
--- /dev/null
+++ b/ninny/src-3/nrktkt/ninny/Annotation.scala
@@ -0,0 +1,48 @@
+package nrktkt.ninny
+
+import scala.quoted._
+
+object Annotation {
+ type Aux[A, O] = Annotation[A] { type Out = O }
+
+ transparent inline given derived[T]: Annotation[T] =
+ ${genAnnotationImpl[T]}
+
+ def genAnnotationImpl[T: Type](using Quotes): Expr[Annotation[T]] = {
+ import quotes.reflect._
+ val classSymbol = TypeRepr.of[T].typeSymbol
+ val objectSymbol = classSymbol.companionModule
+ val tycons = TypeRepr.of[scala.*:[_, _]] match
+ case AppliedType(a, _) => a
+ val (tupleExpr, tupleType) = classSymbol.caseFields.reverse.foldLeft[(Term, TypeRepr)]((Expr(EmptyTuple).asTerm, TypeRepr.of[EmptyTuple.type])){ case ((tpleExpr, tpleTpe), symbol) =>
+ tpleTpe.asType match
+ case ('[t]) =>
+ val valueOpt =
+ symbol.annotations.collect {
+ case Apply(Select(New(ident),_), List(Literal(StringConstant(strVal)))) => strVal
+ } match
+ case head :: next => Some(head)
+ case Nil => None
+ valueOpt match
+ case Some(value) =>
+ val tpe = ConstantType(StringConstant(value))
+ tpe.asType match
+ case '[x] =>
+ (Apply(TypeApply(Select.unique(tpleExpr, "*:"), List(TypeTree.of[x], TypeTree.of[t])), List(Literal(StringConstant(value)))), AppliedType(tycons, List(tpe, tpleTpe)))
+ case None =>
+ (Apply(TypeApply(Select.unique(tpleExpr, "*:"), List(TypeTree.of[Null], TypeTree.of[t])), List('{null}.asTerm)), AppliedType(tycons, List(TypeRepr.of[Null], tpleTpe)))
+ }
+ tupleType.asType match
+ case '[t] =>
+ '{
+ new Annotation[T] {
+ type Out = t
+ def apply(): Out = ${tupleExpr.asExprOf[t]}
+ }.asInstanceOf[Annotation.Aux[T, t]]
+ }
+ }
+}
+trait Annotation[A] {
+ type Out <: Tuple
+ def apply(): Out
+}
diff --git a/ninny/src-3/nrktkt/ninny/Auto.scala b/ninny/src-3/nrktkt/ninny/Auto.scala
new file mode 100644
index 0000000..d840f4c
--- /dev/null
+++ b/ninny/src-3/nrktkt/ninny/Auto.scala
@@ -0,0 +1,41 @@
+package nrktkt.ninny
+
+import scala.deriving.Mirror
+
+trait AutoToJson {
+ implicit inline def lgToJson[
+ A <: Product,
+ OverridingNames <: Tuple](implicit
+ mirror: Mirror.ProductOf[A],
+ names: Annotation.Aux[A, OverridingNames]): ToSomeJson[A] =
+ ToJsonAuto.labelledGenericToJson.toJson
+}
+
+trait AutoFromJson {
+ implicit inline def lgFromJson[
+ A <: Product,
+ Values <: Tuple,
+ Defaults <: Tuple,
+ OverridingNames <: Tuple,
+ Size <: Numlike
+ ](implicit
+ mirror: Mirror.ProductOf[A],
+ ev: Size =:= Auto.WrappedSize[mirror.MirroredElemTypes],
+ defaults: Defaults.Aux[A, Defaults],
+ annotation: Annotation.Aux[A, OverridingNames],
+ from: (Sized[List[String], Size], Defaults) => FromJson[Values]
+ ): FromJson[A] = FromJsonAuto.labelledGenericFromJson.fromJson
+}
+
+object Auto extends AutoToJson with AutoFromJson {
+ private[ninny] type OverrideNames[Names <: Tuple, Overriden <: Tuple] <: Tuple =
+ (Names, Overriden) match
+ case (aHead *: aTail, Null *: bTail) => aHead *: OverrideNames[aTail, bTail]
+ case (aHead *: aTail, str *: bTail) => str *: OverrideNames[aTail, bTail]
+ case (EmptyTuple, _) => EmptyTuple
+
+ private[ninny] type WrappedSize[T <: Tuple] = T match
+ case a *: EmptyTuple => Added[Zero]
+ case a *: b => Added[WrappedSize[b]]
+
+}
diff --git a/ninny/src-3/nrktkt/ninny/DefaultOptions.scala b/ninny/src-3/nrktkt/ninny/DefaultOptions.scala
new file mode 100644
index 0000000..52475ec
--- /dev/null
+++ b/ninny/src-3/nrktkt/ninny/DefaultOptions.scala
@@ -0,0 +1,39 @@
+package nrktkt.ninny
+import scala.quoted._
+
+object DefaultOptions {
+ type Aux[A, O] = DefaultOptions[A] { type Out = O }
+
+ transparent inline given derived[T]: DefaultOptions[T] =
+ ${genDefaultsImpl[T]}
+
+ def genDefaultsImpl[T: Type](using Quotes): Expr[DefaultOptions[T]] = {
+ import quotes.reflect._
+ val classSymbol = TypeRepr.of[T].typeSymbol
+ val objectSymbol = classSymbol.companionModule
+ val tycons = TypeRepr.of[scala.*:[_, _]] match
+ case AppliedType(a, _) => a
+ val (tupleExpr, tupleType) = classSymbol.caseFields.zipWithIndex.reverse.foldLeft[(Term, TypeRepr)]((Expr(EmptyTuple).asTerm, TypeRepr.of[EmptyTuple.type])){ case ((tpleExpr, tpleTpe), (symbol, idx)) =>
+ (tpleTpe.asType, TypeRepr.of[T].memberType(symbol).asType) match
+ case ('[t], '[g]) =>
+ if symbol.flags.is(Flags.HasDefault) then
+ val value = objectSymbol.declaredMethod("$lessinit$greater$default$" + (idx + 1)).head
+ val expr = '{Some(${Select(Ref(objectSymbol), value).asExprOf[g]})}
+ (Apply(TypeApply(Select.unique(tpleExpr, "*:"), List(TypeTree.of[Option[g]], TypeTree.of[t])), List(expr.asTerm)), AppliedType(tycons, List(TypeRepr.of[Option[g]], tpleTpe)))
+ else
+ (Apply(TypeApply(Select.unique(tpleExpr, "*:"), List(TypeTree.of[Option[g]], TypeTree.of[t])), List('{None}.asTerm)), AppliedType(tycons, List(TypeRepr.of[Option[g]], tpleTpe)))
+ }
+ tupleType.asType match
+ case '[t] =>
+ '{
+ new DefaultOptions[T] {
+ type Out = t
+ def apply(): Out = ${tupleExpr.asExprOf[t]}
+ }.asInstanceOf[DefaultOptions.Aux[T, t]]
+ }
+ }
+}
+trait DefaultOptions[A] {
+ type Out <: Tuple
+ def apply(): Out
+}
diff --git a/ninny/src-3/nrktkt/ninny/FromJsonAutoImpl.scala b/ninny/src-3/nrktkt/ninny/FromJsonAutoImpl.scala
index 625d6de..4251c5a 100644
--- a/ninny/src-3/nrktkt/ninny/FromJsonAutoImpl.scala
+++ b/ninny/src-3/nrktkt/ninny/FromJsonAutoImpl.scala
@@ -1,3 +1,59 @@
package nrktkt.ninny
-trait FromJsonAutoImpl {}
+import scala.annotation.nowarn
+import scala.deriving.Mirror
+import nrktkt.ninny.DefaultOptions._
+import scala.compiletime.ops.int
+import scala.compiletime.ops.int._
+
+trait FromJsonAutoImpl {
+
+ implicit def useDefaults[A, O <: Tuple](implicit
+ defaults: DefaultOptions.Aux[A, O]
+ ): Defaults.Aux[A, O] =
+ new Defaults[A] {
+ type Out = O
+ def apply() = defaults()
+ }
+
+ implicit inline def labelledGenericFromJson[
+ A <: Product,
+ Values <: Tuple,
+ Defaults <: Tuple,
+ OverridingNames <: Tuple,
+ Size <: Numlike
+ ](implicit
+ mirror: Mirror.ProductOf[A],
+ ev: Size =:= Auto.WrappedSize[mirror.MirroredElemTypes],
+ defaults: Defaults.Aux[A, Defaults],
+ annotation: Annotation.Aux[A, OverridingNames],
+ from: (Sized[List[String], Size], Defaults) => FromJson[Values]
+ ): FromJsonAuto[A] = {
+ val names = Sized[A, OverridingNames, Size](mirror)
+ val fromJson = from(names, defaults()).map(mirror.fromProduct(_))
+ new FromJsonAuto[A](fromJson)
+ }
+
+}
+
+trait Defaults[A] {
+ type Out <: Tuple
+ def apply(): Out
+}
+
+object Defaults {
+ type Aux[A, O <: Tuple] = Defaults[A] { type Out = O }
+
+ implicit def ignoreDefaults[A, O <: Tuple](implicit
+ defaults: DefaultOptions.Aux[A, O],
+ ): Defaults.Aux[A, O] =
+ new Defaults[A] {
+ type Out = O
+ def apply() =
+ def makeEmptyTuple(tuple: Tuple): Tuple =
+ tuple match
+ case head *: tail => None *: makeEmptyTuple(tail)
+ case EmptyTuple => EmptyTuple
+ makeEmptyTuple(defaults()).asInstanceOf[Out]
+ }
+}
diff --git a/ninny/src-3/nrktkt/ninny/JsonName.scala b/ninny/src-3/nrktkt/ninny/JsonName.scala
new file mode 100644
index 0000000..4299a5b
--- /dev/null
+++ b/ninny/src-3/nrktkt/ninny/JsonName.scala
@@ -0,0 +1,5 @@
+package nrktkt.ninny
+
+import scala.annotation.StaticAnnotation
+
+case class JsonName(name: String) extends StaticAnnotation
diff --git a/ninny/src-3/nrktkt/ninny/ToJsonAutoImpl.scala b/ninny/src-3/nrktkt/ninny/ToJsonAutoImpl.scala
index d6c0cf1..a9b591f 100644
--- a/ninny/src-3/nrktkt/ninny/ToJsonAutoImpl.scala
+++ b/ninny/src-3/nrktkt/ninny/ToJsonAutoImpl.scala
@@ -1,5 +1,19 @@
package nrktkt.ninny
+import scala.deriving.Mirror
+import scala.deriving.Mirror.Sum
+import scala.collection.View.Zip
+
trait ToJsonAutoImpl {
-
+
+ implicit inline def labelledGenericToJson[A <: Product, OverridingNames <: Tuple](using mirror: Mirror.ProductOf[A], annotations: Annotation.Aux[A, OverridingNames]): ToJsonAuto[A] = {
+ new ToJsonAuto[A]((a: A) => {
+ val keys = scala.compiletime.constValueTuple[Auto.OverrideNames[mirror.MirroredElemLabels, OverridingNames]]
+ val values = Tuple.fromProductTyped(a)
+ val zip = keys.zip(values)
+
+ scala.compiletime.summonInline[ToSomeJsonObject[Tuple.Zip[Auto.OverrideNames[mirror.MirroredElemLabels, OverridingNames], mirror.MirroredElemTypes]]].toSome(zip.asInstanceOf[Tuple.Zip[Auto.OverrideNames[mirror.MirroredElemLabels, OverridingNames], mirror.MirroredElemTypes]])
+ })
+ }
+
}
diff --git a/ninny/src-3/nrktkt/ninny/VersionSpecificFromJsonInstances.scala b/ninny/src-3/nrktkt/ninny/VersionSpecificFromJsonInstances.scala
index dcd173d..b616165 100644
--- a/ninny/src-3/nrktkt/ninny/VersionSpecificFromJsonInstances.scala
+++ b/ninny/src-3/nrktkt/ninny/VersionSpecificFromJsonInstances.scala
@@ -1,5 +1,75 @@
package nrktkt.ninny
+import scala.util.Success
+import scala.annotation.nowarn
+import scala.compiletime.ops.int.{+, -, S}
+
+import nrktkt.ninny.ast.JsonValue
+import scala.util.Failure
+import scala.deriving.Mirror
+import scala.util.Try
+
trait VersionSpecificFromJsonInstances {
-
+
+ implicit def recordFromJson[
+ Head,
+ DefaultHead <: Option[Head],
+ Tail <: Tuple,
+ DefaultTail <: Tuple,
+ TailLen <: Numlike
+ ](implicit
+ headFromJson: FromJson[Head],
+ tailFromJson: (
+ Sized[List[String], TailLen],
+ DefaultTail
+ ) => FromJson[Tail]
+ ): (
+ Sized[List[String], Added[TailLen]],
+ DefaultHead *: DefaultTail
+ ) => FromJson[Head *: Tail] = (names, defaults) => {
+ val defaultHeadFromJson: FromJson[Head] = maybe =>
+ (maybe, defaults.head) match {
+ case (maybe: Some[JsonValue], _) => headFromJson.from(maybe)
+ case (_, default: Some[Head]) => Success(default.value)
+ case _ => headFromJson.from(None)
+ }
+
+ FromJson.fromSome { json =>
+ for {
+ head <- defaultHeadFromJson
+ .from(json / Sized.value(names).head)
+ .recoverWith {
+ case e: JsonFieldException =>
+ Failure(
+ new JsonFieldException(
+ e.message,
+ s"${Sized.value(names).head}.${e.field}",
+ e
+ )
+ )
+ case e: Exception =>
+ Failure(new JsonFieldException(e.getMessage, Sized.value(names).head, e))
+ }
+ tail <- tailFromJson(names.tail, defaults.tail).from(json)
+ } yield head *: tail
+ }
+ }
+
+ implicit val emptyTupleFromJson: ((Sized[List[String], Zero]), EmptyTuple) => FromJson[EmptyTuple] =
+ (_, _) => _ => Success(EmptyTuple)
}
+
+opaque type Sized[l <: List[String], Size] = List[String]
+
+object Sized {
+ def value[L <: List[String], Size](a: Sized[L, Size]): List[String] = a
+ inline def apply[T <: Product, OverridingNames <: Tuple, Size <: Numlike](mirror: Mirror.ProductOf[T]): Sized[List[String], Size] =
+ scala.compiletime.constValueTuple[Auto.OverrideNames[mirror.MirroredElemLabels, OverridingNames]].asInstanceOf[Tuple].toList.asInstanceOf[List[String]]
+}
+
+extension [L <: List[String], Size <: Numlike] (s: Sized[L, Added[Size]]) def tail: Sized[L, Size] = s.tail
+
+
+type Numlike
+type Added[T] <: Numlike
+type Zero <: Numlike
\ No newline at end of file
diff --git a/ninny/src-3/nrktkt/ninny/VersionSpecificToJsonInstances.scala b/ninny/src-3/nrktkt/ninny/VersionSpecificToJsonInstances.scala
index 172909e..dcdf418 100644
--- a/ninny/src-3/nrktkt/ninny/VersionSpecificToJsonInstances.scala
+++ b/ninny/src-3/nrktkt/ninny/VersionSpecificToJsonInstances.scala
@@ -1,5 +1,29 @@
package nrktkt.ninny
+import nrktkt.ninny.ast.JsonObject
+import nrktkt.ninny.NullPointerBehavior
+import nrktkt.ninny.NullPointerBehavior.Handle
+
trait VersionSpecificToJsonInstances {
-
+ implicit def recordToJson[V, G <: String, Tail <: Tuple](implicit
+ valueToJson: ToJson[V],
+ tailToJson: ToSomeJsonObject[Tail],
+ nullPointerBehavior: NullPointerBehavior
+ ): ToSomeJsonObject[(G, V) *: Tail] = {
+ ToJson { case (name, value) *: tail =>
+ val tailJson = tailToJson.toSome(tail)
+ nullPointerBehavior match {
+ case Handle(behavior) if value == null =>
+ tailJson + (name -> behavior())
+ case _ =>
+ val maybeValueJson = valueToJson.to(value)
+ maybeValueJson match {
+ case Some(valueJson) => tailJson + (name -> valueJson)
+ case None => tailJson
+ }
+ }
+ }
+ }
+
+ implicit val hNilToJson: ToSomeJsonObject[EmptyTuple] = _ => JsonObject(Map.empty)
}
diff --git a/ninny/src/nrktkt/ninny/FromJsonInstances.scala b/ninny/src/nrktkt/ninny/FromJsonInstances.scala
index eaa09e3..3e30eb8 100644
--- a/ninny/src/nrktkt/ninny/FromJsonInstances.scala
+++ b/ninny/src/nrktkt/ninny/FromJsonInstances.scala
@@ -233,9 +233,6 @@ trait FromJsonInstances
object FromJsonInstances extends FromJsonInstances
trait LowPriorityFromJsonInstances {
- // this roundabout way to import compiler flag for higher kinded types avoids a deprecation warning when building for 2.13
- protected implicit lazy val hkhack: languageFeature.higherKinds.type =
- scala.languageFeature.higherKinds
implicit def collectionFromJson[F[_], A](implicit
factory: Factory[A, F[A]],
diff --git a/ninny/src-2/nrktkt/ninny/NullPointerBehavior.scala b/ninny/src/nrktkt/ninny/NullPointerBehavior.scala
similarity index 87%
rename from ninny/src-2/nrktkt/ninny/NullPointerBehavior.scala
rename to ninny/src/nrktkt/ninny/NullPointerBehavior.scala
index 19600b8..57e5979 100644
--- a/ninny/src-2/nrktkt/ninny/NullPointerBehavior.scala
+++ b/ninny/src/nrktkt/ninny/NullPointerBehavior.scala
@@ -14,5 +14,5 @@ object NullPointerBehavior {
val someNull = Some(JsonNull)
() => someNull
}
- implicit def default = PassThrough
+ implicit def default: NullPointerBehavior = PassThrough
}
diff --git a/ninny/test/src-3/nrktkt/ninny/userguide/ForProductN.scala b/ninny/test/src-3/nrktkt/ninny/userguide/ForProductN.scala
new file mode 100644
index 0000000..f7ae5a2
--- /dev/null
+++ b/ninny/test/src-3/nrktkt/ninny/userguide/ForProductN.scala
@@ -0,0 +1,25 @@
+package nrktkt.ninny.userguide
+
+import nrktkt.ninny._
+
+object ForProductN extends App {
+// format: Off
+
+case class Address(street: String, zip: String)
+
+val fromJson: FromJson[Address] =
+ FromJson.forProduct2("street", "zip_code")(Address.apply)
+
+implicit
+val toJson: ToSomeJson[Address] =
+ ToJson.forProduct2("street", "zip_code")(Tuple.fromProductTyped)
+
+val toAndFromJson: ToAndFromJson[Address] =
+ ToAndFromJson.forProduct2("street", "zip_code")(
+ Address.apply, Tuple.fromProductTyped
+ )
+
+Address(street = "710 Ashbury St", zip = "94117").toSomeJson
+// {"street":"710 Ashbury St","zip_code":"94117"}
+
+}
diff --git a/ninny/test/src-2/nrktkt/ninny/JsonSpec.scala b/ninny/test/src/nrktkt/ninny/JsonSpec.scala
similarity index 90%
rename from ninny/test/src-2/nrktkt/ninny/JsonSpec.scala
rename to ninny/test/src/nrktkt/ninny/JsonSpec.scala
index ea1f7f1..8466ab7 100644
--- a/ninny/test/src-2/nrktkt/ninny/JsonSpec.scala
+++ b/ninny/test/src/nrktkt/ninny/JsonSpec.scala
@@ -30,11 +30,11 @@ class JsonSpec
val sampleValues = obj(
"string" ~> """¯\_(ツ)_/¯""",
"number" ~> 1.79e308,
- "bool" ~> true,
- "false" ~> false,
- "null" ~> JsonNull,
- "unit" ~> ((): Unit),
- "some" ~> "str"
+ "bool" ~> true,
+ "false" ~> false,
+ "null" ~> JsonNull,
+ "unit" ~> ((): Unit),
+ "some" ~> "str"
)
val sampleArray =
@@ -44,7 +44,7 @@ class JsonSpec
JsonObject(
sampleValues.values ++ obj(
"object" ~> sampleValues,
- "array" ~> sampleArray
+ "array" ~> sampleArray
).values
)
@@ -95,11 +95,11 @@ class JsonSpec
val sampleValuesAst = obj(
"string" ~> """¯\_(ツ)_/¯""",
"number" ~> 1.79e308,
- "bool" ~> true,
- "false" ~> false,
- "null" ~> JsonNull,
- "unit" ~> ((): Unit),
- "some" ~> Some("str")
+ "bool" ~> true,
+ "false" ~> false,
+ "null" ~> JsonNull,
+ "unit" ~> ((): Unit),
+ "some" ~> Some("str")
)
val sampleValuesObj = SampleValues(
@@ -184,39 +184,39 @@ class JsonSpec
val exampleObjectAst = obj(
"Image" ~> obj(
- "Width" ~> 800,
+ "Width" ~> 800,
"Height" ~> 600,
- "Title" ~> "View from 15th Floor",
+ "Title" ~> "View from 15th Floor",
"Thumbnail" ~> obj(
- "Url" ~> "http://www.example.com/image/481989943",
+ "Url" ~> "http://www.example.com/image/481989943",
"Height" ~> 125,
- "Width" ~> 100
+ "Width" ~> 100
),
"Animated" ~> false,
- "IDs" ~> arr(116, 943, 234, 38793)
+ "IDs" ~> arr(116, 943, 234, 38793)
)
)
val exampleArrayAst = arr(
obj(
"precision" ~> "zip",
- "Latitude" ~> 37.7668,
+ "Latitude" ~> 37.7668,
"Longitude" ~> -122.3959,
- "Address" ~> "",
- "City" ~> "SAN FRANCISCO",
- "State" ~> "CA",
- "Zip" ~> "94107",
- "Country" ~> "US"
+ "Address" ~> "",
+ "City" ~> "SAN FRANCISCO",
+ "State" ~> "CA",
+ "Zip" ~> "94107",
+ "Country" ~> "US"
),
obj(
"precision" ~> "zip",
- "Latitude" ~> 37.371991,
+ "Latitude" ~> 37.371991,
"Longitude" ~> -122.026020,
- "Address" ~> "",
- "City" ~> "SUNNYVALE",
- "State" ~> "CA",
- "Zip" ~> "94085",
- "Country" ~> "US"
+ "Address" ~> "",
+ "City" ~> "SUNNYVALE",
+ "State" ~> "CA",
+ "Zip" ~> "94085",
+ "Country" ~> "US"
)
)
@@ -245,13 +245,13 @@ class JsonSpec
implicit val toJson: ToSomeJson[Image] = a =>
obj(
- "Width" ~> a.Width,
- "Height" ~> a.Height,
- "Title" ~> a.Title,
+ "Width" ~> a.Width,
+ "Height" ~> a.Height,
+ "Title" ~> a.Title,
"Thumbnail" ~> a.Thumbnail,
- "Url" ~> a.Url,
- "Animated" ~> a.Animated,
- "IDs" ~> (if (a.IDs.isEmpty) None else Some(a.IDs))
+ "Url" ~> a.Url,
+ "Animated" ~> a.Animated,
+ "IDs" ~> (if (a.IDs.isEmpty) None else Some(a.IDs))
)
}
@@ -282,13 +282,13 @@ class JsonSpec
implicit val toJson: ToSomeJson[Address] = a =>
obj(
"precision" ~> a.precision,
- "Latitude" ~> a.Latitude,
+ "Latitude" ~> a.Latitude,
"Longitude" ~> a.Longitude,
- "Address" ~> a.Address,
- "City" ~> a.City,
- "State" ~> a.State,
- "Zip" ~> a.Zip,
- "Country" ~> a.Country
+ "Address" ~> a.Address,
+ "City" ~> a.City,
+ "State" ~> a.State,
+ "Zip" ~> a.Zip,
+ "Country" ~> a.Country
)
}
@@ -512,7 +512,6 @@ class JsonSpec
head :++ tail shouldEqual arr(1, 2, 3, 4, 5, 6)
}
-
"JsonBlob" should "encode and decode to base64" in {
val bytes = new Array[Byte](16)
Random.nextBytes(bytes)
@@ -624,7 +623,7 @@ class JsonSpec
y: Int,
z: Int
)
- implicit val json = ToAndFromJson.auto[Big]
+ implicit val json: ToAndFromJson[Big] = ToAndFromJson.auto
val big = Big(1, 2, 2, 1234, 1234, 124, 1234, 1234, 1234, 1234, 123, 2134,
1324, 1234, 1234, 1, 234, 1234, 14, 23, 132, 13, 431, 31, 3412, 1432)
Json
@@ -636,7 +635,7 @@ class JsonSpec
"annotations" should "work" in {
case class Example(@JsonName("baz") foo: String, bop: Int)
- implicit val toFromJson = ToAndFromJson.auto[Example]
+ implicit val toFromJson: ToAndFromJson[Example] = ToAndFromJson.auto
val example = Example("bar", 1)
val js = example.toSomeJson
@@ -648,9 +647,9 @@ class JsonSpec
case class Example(qix: Int, foo: String = "bar")
"auto from json" should "read defaults for absent fields" in {
- implicit val toFromJson = {
+ implicit val toFromJson: ToAndFromJson[Example] = {
import FromJsonAuto.useDefaults
- ToAndFromJson.auto[Example]
+ ToAndFromJson.auto
}
obj("qix" ~> 1).to[Example].success.value shouldEqual Example(1)
@@ -676,17 +675,17 @@ class JsonSpec
if (i == null) JsonNumber(0) else JsonDouble(i.toDouble)
"NullPointerBehavior" should "pass null pointers to typeclass instances by default" in {
- val example = Example(null)
- implicit val exampleToJson = ToJson.auto[Example]
- val json = example.toSomeJson
+ val example = Example(null)
+ implicit val exampleToJson: ToSomeJsonObject[Example] = ToJson.auto
+ val json = example.toSomeJson
(json / "i").value shouldEqual JsonNumber(0)
}
it should "use behavior when in scope" in {
val example = Example(null)
implicit val nullPointerBehavior = NullPointerBehavior.WriteNull
- implicit val exampleToJson = ToJson.auto[Example]
- val json = example.toSomeJson
+ implicit val exampleToJson: ToSomeJsonObject[Example] = ToJson.auto
+ val json = example.toSomeJson
(json / "i").value shouldEqual JsonNull
}
}
diff --git a/ninny/test/src-2/nrktkt/ninny/example/Example.scala b/ninny/test/src/nrktkt/ninny/example/Example.scala
similarity index 100%
rename from ninny/test/src-2/nrktkt/ninny/example/Example.scala
rename to ninny/test/src/nrktkt/ninny/example/Example.scala
diff --git a/ninny/test/src-2/nrktkt/ninny/example/Userguide.scala b/ninny/test/src/nrktkt/ninny/example/Userguide.scala
similarity index 93%
rename from ninny/test/src-2/nrktkt/ninny/example/Userguide.scala
rename to ninny/test/src/nrktkt/ninny/example/Userguide.scala
index 76663cc..aa9394f 100644
--- a/ninny/test/src-2/nrktkt/ninny/example/Userguide.scala
+++ b/ninny/test/src/nrktkt/ninny/example/Userguide.scala
@@ -143,7 +143,7 @@ implicit val personToJson: ToSomeJson[Person] = p =>
"age" ~> p.age
)
-implicit val personFromJson = FromJson.fromSome[Person](json =>
+implicit val personFromJson: FromJson[Person] = FromJson.fromSome(json =>
for {
first <- json.firstName.to[String]
last <- json.lastName.to[String]
@@ -170,11 +170,11 @@ Json.parse("").to[Person]: Try[Person]
implement ToSomeJson instead of ToJson if your object always produces
some kind of JSON. this is a common case.
*/
-implicit val addressToJson = ToAndFromJson.auto[Address]
+implicit val addressToJson: ToAndFromJson[Address] = ToAndFromJson.auto
-implicit val personToJson = ToJson.auto[Person]
+implicit val personToJson: ToSomeJsonObject[Person] = ToJson.auto
-implicit val personFromJson = FromJson.auto[Person]
+implicit val personFromJson: FromJson[Person] = FromJson.auto
Person(
"John",
@@ -207,7 +207,7 @@ Json.parse("").to[Person]: Try[Person]
implicit val nullPointerBehavior =
NullPointerBehavior.Handle(() => Some(JsonString("unknown")))
-implicit val addressToJson = ToJson.auto[Address]
+implicit val addressToJson: ToSomeJsonObject[Address] = ToJson.auto
val address = Address(zip = "94117", street = null)
address.toSomeJson // {"zip": "94117", "street":"unknown"}
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/Annotations.scala b/ninny/test/src/nrktkt/ninny/userguide/Annotations.scala
similarity index 81%
rename from ninny/test/src-2/nrktkt/ninny/userguide/Annotations.scala
rename to ninny/test/src/nrktkt/ninny/userguide/Annotations.scala
index 12e5138..60a9362 100644
--- a/ninny/test/src-2/nrktkt/ninny/userguide/Annotations.scala
+++ b/ninny/test/src/nrktkt/ninny/userguide/Annotations.scala
@@ -13,7 +13,7 @@ case class Example(
int: Int
)
-implicit val toFromJson = ToAndFromJson.auto[Example]
+implicit val toFromJson: ToAndFromJson[Example] = ToAndFromJson.auto
Example("foo", 1).toSomeJson
// {"string_field":"foo", "int":1}
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/DefaultValues.scala b/ninny/test/src/nrktkt/ninny/userguide/DefaultValues.scala
similarity index 83%
rename from ninny/test/src-2/nrktkt/ninny/userguide/DefaultValues.scala
rename to ninny/test/src/nrktkt/ninny/userguide/DefaultValues.scala
index 591d678..379855e 100644
--- a/ninny/test/src-2/nrktkt/ninny/userguide/DefaultValues.scala
+++ b/ninny/test/src/nrktkt/ninny/userguide/DefaultValues.scala
@@ -8,9 +8,9 @@ object DefaultValues extends App {
case class User(name: String, admin: Boolean = false)
-implicit val userFromJson = {
+implicit val userFromJson: FromJson[User] = {
import nrktkt.ninny.FromJsonAuto.useDefaults
- FromJson.auto[User]
+ FromJson.auto
}
obj("name" --> "Alice").to[User]
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/DomainFrom.scala b/ninny/test/src/nrktkt/ninny/userguide/DomainFrom.scala
similarity index 100%
rename from ninny/test/src-2/nrktkt/ninny/userguide/DomainFrom.scala
rename to ninny/test/src/nrktkt/ninny/userguide/DomainFrom.scala
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/DomainTo.scala b/ninny/test/src/nrktkt/ninny/userguide/DomainTo.scala
similarity index 100%
rename from ninny/test/src-2/nrktkt/ninny/userguide/DomainTo.scala
rename to ninny/test/src/nrktkt/ninny/userguide/DomainTo.scala
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/FullAuto.scala b/ninny/test/src/nrktkt/ninny/userguide/FullAuto.scala
similarity index 91%
rename from ninny/test/src-2/nrktkt/ninny/userguide/FullAuto.scala
rename to ninny/test/src/nrktkt/ninny/userguide/FullAuto.scala
index dc94d39..9335de9 100644
--- a/ninny/test/src-2/nrktkt/ninny/userguide/FullAuto.scala
+++ b/ninny/test/src/nrktkt/ninny/userguide/FullAuto.scala
@@ -2,6 +2,7 @@ package nrktkt.ninny.userguide
import nrktkt.ninny.userguide.DomainFrom.Person
import nrktkt.ninny.userguide.DomainFrom.Address
+import nrktkt.ninny.AnySyntax
object FullAuto {
// format: off
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/Reading.scala b/ninny/test/src/nrktkt/ninny/userguide/Reading.scala
similarity index 100%
rename from ninny/test/src-2/nrktkt/ninny/userguide/Reading.scala
rename to ninny/test/src/nrktkt/ninny/userguide/Reading.scala
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/SemiAuto.scala b/ninny/test/src/nrktkt/ninny/userguide/SemiAuto.scala
similarity index 61%
rename from ninny/test/src-2/nrktkt/ninny/userguide/SemiAuto.scala
rename to ninny/test/src/nrktkt/ninny/userguide/SemiAuto.scala
index cc2182f..98cc96f 100644
--- a/ninny/test/src-2/nrktkt/ninny/userguide/SemiAuto.scala
+++ b/ninny/test/src/nrktkt/ninny/userguide/SemiAuto.scala
@@ -9,9 +9,9 @@ object SemiAuto {
import nrktkt.ninny._
// generate ToJson and FromJson at the same time with ToAndFromJson
-implicit val toAndFromJson = ToAndFromJson.auto[Address]
+implicit val toAndFromJson: ToAndFromJson[Address] = ToAndFromJson.auto
// or generate them separately
-implicit val fromJson = FromJson.auto[Person]
-implicit val toJson = ToJson.auto[Person]
+implicit val fromJson: FromJson[Person] = FromJson.auto
+implicit val toJson: ToJson[Person] = ToJson.auto
}
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/Updating.scala b/ninny/test/src/nrktkt/ninny/userguide/Updating.scala
similarity index 100%
rename from ninny/test/src-2/nrktkt/ninny/userguide/Updating.scala
rename to ninny/test/src/nrktkt/ninny/userguide/Updating.scala
diff --git a/ninny/test/src-2/nrktkt/ninny/userguide/Writing.scala b/ninny/test/src/nrktkt/ninny/userguide/Writing.scala
similarity index 100%
rename from ninny/test/src-2/nrktkt/ninny/userguide/Writing.scala
rename to ninny/test/src/nrktkt/ninny/userguide/Writing.scala
diff --git a/old-namespace/src-3/io/github/kag0/ninny/VersionSpecificPackage.scala b/old-namespace/src-3/io/github/kag0/ninny/VersionSpecificPackage.scala
index e0ed395..c483e87 100644
--- a/old-namespace/src-3/io/github/kag0/ninny/VersionSpecificPackage.scala
+++ b/old-namespace/src-3/io/github/kag0/ninny/VersionSpecificPackage.scala
@@ -1,3 +1,9 @@
package io.github.kag0.ninny
-trait VersionSpecificPackage {}
+trait VersionSpecificPackage {
+ val Auto = nrktkt.ninny.Auto
+ val FromJsonAuto = nrktkt.ninny.FromJsonAuto
+
+ type JsonName = nrktkt.ninny.JsonName
+ val JsonName = nrktkt.ninny.JsonName
+}