From 108af0821ea07da63c36e30a93126f6c00ad39ec Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Fri, 10 May 2024 12:42:51 +0300 Subject: [PATCH 1/4] feat: implement interop for newtype --- build.sbt | 19 ++++++++++++++++ .../zio/json/interop/newtype/package.scala | 19 ++++++++++++++++ .../json/interop/newtype/NewtypeSpec.scala | 22 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala create mode 100644 zio-json-interop-newtype/shared/src/test/scala/zio/json/interop/newtype/NewtypeSpec.scala diff --git a/build.sbt b/build.sbt index aa577ae1f..d16798325 100644 --- a/build.sbt +++ b/build.sbt @@ -79,6 +79,8 @@ lazy val zioJsonRoot = project zioJsonInteropScalaz7x.js, zioJsonInteropScalaz7x.jvm, zioJsonInteropScalaz7x.native, + zioJsonInteropNewtype.js, + zioJsonInteropNewtype.jvm, zioJsonGolden ) @@ -357,6 +359,22 @@ lazy val zioJsonInteropRefined = crossProject(JSPlatform, JVMPlatform, NativePla ) .enablePlugins(BuildInfoPlugin) +lazy val zioJsonInteropNewtype = crossProject(JSPlatform, JVMPlatform) + .in(file("zio-json-interop-newtype")) + .dependsOn(zioJson) + .settings(stdSettings("zio-json-interop-newtype")) + .settings(buildInfoSettings("zio.json.interop.newtype")) + .settings(macroExpansionSettings) + .settings( + libraryDependencies ++= Seq( + "io.estatico" %%% "newtype" % "0.4.4", + "dev.zio" %%% "zio-test" % zioVersion % "test", + "dev.zio" %%% "zio-test-sbt" % zioVersion % "test" + ), + testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework") + ) + .enablePlugins(BuildInfoPlugin) + lazy val zioJsonInteropScalaz7x = crossProject(JSPlatform, JVMPlatform, NativePlatform) .in(file("zio-json-interop-scalaz7x")) .dependsOn(zioJson) @@ -398,6 +416,7 @@ lazy val docs = project zioJsonInteropHttp4s, zioJsonInteropRefined.jvm, zioJsonInteropScalaz7x.jvm, + zioJsonInteropNewtype.jvm, zioJsonGolden ), readmeAcknowledgement := diff --git a/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala b/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala new file mode 100644 index 000000000..81cf65374 --- /dev/null +++ b/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala @@ -0,0 +1,19 @@ +package zio.json.interop + +import io.estatico.newtype.Coercible +import io.estatico.newtype.ops._ +import zio.json.{ JsonDecoder, JsonEncoder, JsonFieldDecoder, JsonFieldEncoder } + +package object newtype { + implicit def coercibleDecoder[A: Coercible[B, *], B: JsonDecoder]: JsonDecoder[A] = + JsonDecoder[B].map(_.coerce[A]) + + implicit def coercibleEncoder[A: Coercible[*, B], B: JsonEncoder]: JsonEncoder[A] = + JsonEncoder[B].contramap(_.coerce[B]) + + implicit def coercibleKeyDecoder[A: Coercible[B, *], B: JsonFieldDecoder]: JsonFieldDecoder[A] = + JsonFieldDecoder[B].map(_.coerce[A]) + + implicit def coercibleKeyEncoder[A: Coercible[*, B], B: JsonFieldEncoder]: JsonFieldEncoder[A] = + JsonFieldEncoder[B].contramap(_.coerce[B]) +} diff --git a/zio-json-interop-newtype/shared/src/test/scala/zio/json/interop/newtype/NewtypeSpec.scala b/zio-json-interop-newtype/shared/src/test/scala/zio/json/interop/newtype/NewtypeSpec.scala new file mode 100644 index 000000000..b03933d2e --- /dev/null +++ b/zio-json-interop-newtype/shared/src/test/scala/zio/json/interop/newtype/NewtypeSpec.scala @@ -0,0 +1,22 @@ +package zio.json.interop.newtype + +import io.estatico.newtype.macros.newtype +import zio.json.{ DecoderOps, DeriveJsonDecoder, DeriveJsonEncoder, JsonDecoder, JsonEncoder } +import zio.test.Assertion.{ equalTo, isRight } +import zio.test.{ Spec, ZIOSpecDefault, assert, assertTrue } + +object NewtypeSpec extends ZIOSpecDefault { + override def spec: Spec[Environment, Any] = suite("newtype")( + test("newtype") { + assert("""{"name":"fommil"}""".fromJson[Person])(isRight(equalTo(Person(Name("fommil"))))) && + assertTrue(Person(Name("fommil")).toJson == """{"name":"fommil"}""") + } + ) + + @newtype case class Name(value: String) + case class Person(name: Name) + object Person { + implicit val encoder: JsonEncoder[Person] = DeriveJsonEncoder.gen[Person] + implicit val decoder: JsonDecoder[Person] = DeriveJsonDecoder.gen[Person] + } +} From 3b04d2ebbabdbc2bf429063504f2d4765c177009 Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Fri, 10 May 2024 12:52:27 +0300 Subject: [PATCH 2/4] update readme --- .github/workflows/site.yml | 4 +--- README.md | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index 722f7f425..73e43e749 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -1,4 +1,4 @@ -# This file was autogenerated using `zio-sbt-website` via `sbt generateGithubWorkflow` +# This file was autogenerated using `zio-sbt-website` via `sbt generateGithubWorkflow` # task and should be included in the git repository. Please do not edit it manually. name: Website @@ -29,8 +29,6 @@ jobs: check-latest: true - name: Check if the README file is up to date run: sbt docs/checkReadme - - name: Check if the site workflow is up to date - run: sbt docs/checkGithubWorkflow - name: Check artifacts build process run: sbt +publishLocal - name: Check website build process diff --git a/README.md b/README.md index 1018ffe9c..171044685 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [ZIO Json](https://github.com/zio/zio-json) is a fast and secure JSON library with tight ZIO integration. -[![Production Ready](https://img.shields.io/badge/Project%20Stage-Production%20Ready-brightgreen.svg)](https://github.com/zio/zio/wiki/Project-Stages) ![CI Badge](https://github.com/zio/zio-json/workflows/CI/badge.svg) [![Sonatype Snapshots](https://img.shields.io/nexus/s/https/oss.sonatype.org/dev.zio/zio-json_2.13.svg?label=Sonatype%20Snapshot)](https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-json_2.13/) [![ZIO JSON](https://img.shields.io/github/stars/zio/zio-json?style=social)](https://github.com/zio/zio-json) +[![Production Ready](https://img.shields.io/badge/Project%20Stage-Production%20Ready-brightgreen.svg)](https://github.com/zio/zio/wiki/Project-Stages) ![CI Badge](https://github.com/zio/zio-json/workflows/CI/badge.svg) [![Sonatype Releases](https://img.shields.io/nexus/r/https/oss.sonatype.org/dev.zio/zio-json_2.13.svg?label=Sonatype%20Release)](https://oss.sonatype.org/content/repositories/releases/dev/zio/zio-json_2.13/) [![Sonatype Snapshots](https://img.shields.io/nexus/s/https/oss.sonatype.org/dev.zio/zio-json_2.13.svg?label=Sonatype%20Snapshot)](https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-json_2.13/) [![javadoc](https://javadoc.io/badge2/dev.zio/zio-json-docs_2.13/javadoc.svg)](https://javadoc.io/doc/dev.zio/zio-json-docs_2.13) [![ZIO JSON](https://img.shields.io/github/stars/zio/zio-json?style=social)](https://github.com/zio/zio-json) ## Introduction @@ -25,7 +25,7 @@ The goal of this project is to create the best all-round JSON library for Scala: In order to use this library, we need to add the following line in our `build.sbt` file: ```scala -libraryDependencies += "dev.zio" %% "zio-json" % "" +libraryDependencies += "dev.zio" %% "zio-json" % "0.6.2" ``` ## Example From 5b7e28cf4e5a8b1d35eadb6ca8ace6f09e25d71d Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Fri, 10 May 2024 13:16:12 +0300 Subject: [PATCH 3/4] fix ci --- build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index d16798325..64e5ec843 100644 --- a/build.sbt +++ b/build.sbt @@ -32,12 +32,12 @@ addCommandAlias( addCommandAlias( "testScala2JVM", - "zioJsonMacrosJVM/test; zioJsonInteropRefinedJVM/test" + "zioJsonMacrosJVM/test; zioJsonInteropRefinedJVM/test; zioJsonInteropNewtypeJVM/test" ) addCommandAlias( "testScala2JS", - "zioJsonMacrosJS/test; zioJsonInteropRefinedJS/test" + "zioJsonMacrosJS/test; zioJsonInteropRefinedJS/test; zioJsonInteropNewtypeJS/test" ) addCommandAlias( @@ -371,6 +371,7 @@ lazy val zioJsonInteropNewtype = crossProject(JSPlatform, JVMPlatform) "dev.zio" %%% "zio-test" % zioVersion % "test", "dev.zio" %%% "zio-test-sbt" % zioVersion % "test" ), + scalacOptions += "-language:implicitConversions", testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework") ) .enablePlugins(BuildInfoPlugin) @@ -400,7 +401,8 @@ lazy val docs = project zioJsonMacrosJVM, zioJsonInteropHttp4s, zioJsonInteropRefined.jvm, - zioJsonInteropScalaz7x.jvm + zioJsonInteropScalaz7x.jvm, + zioJsonInteropNewtype.jvm ) .settings( crossScalaVersions -= ScalaDotty, From c0a865ac133307ae80104a8728a84620c6fa7cee Mon Sep 17 00:00:00 2001 From: Grigorii Berezin Date: Sun, 12 May 2024 22:00:48 +0300 Subject: [PATCH 4/4] chore: try to fix for publish --- .../src/main/scala/zio/json/interop/newtype/package.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala b/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala index 81cf65374..e439e1e8d 100644 --- a/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala +++ b/zio-json-interop-newtype/shared/src/main/scala/zio/json/interop/newtype/package.scala @@ -5,15 +5,15 @@ import io.estatico.newtype.ops._ import zio.json.{ JsonDecoder, JsonEncoder, JsonFieldDecoder, JsonFieldEncoder } package object newtype { - implicit def coercibleDecoder[A: Coercible[B, *], B: JsonDecoder]: JsonDecoder[A] = + implicit def coercibleDecoder[B: JsonDecoder, A](implicit coerce: Coercible[B, A]): JsonDecoder[A] = JsonDecoder[B].map(_.coerce[A]) - implicit def coercibleEncoder[A: Coercible[*, B], B: JsonEncoder]: JsonEncoder[A] = + implicit def coercibleEncoder[B: JsonEncoder, A](implicit coerce: Coercible[A, B]): JsonEncoder[A] = JsonEncoder[B].contramap(_.coerce[B]) - implicit def coercibleKeyDecoder[A: Coercible[B, *], B: JsonFieldDecoder]: JsonFieldDecoder[A] = + implicit def coercibleKeyDecoder[B: JsonFieldDecoder, A](implicit coerce: Coercible[B, A]): JsonFieldDecoder[A] = JsonFieldDecoder[B].map(_.coerce[A]) - implicit def coercibleKeyEncoder[A: Coercible[*, B], B: JsonFieldEncoder]: JsonFieldEncoder[A] = + implicit def coercibleKeyEncoder[B: JsonFieldEncoder, A](implicit coerce: Coercible[A, B]): JsonFieldEncoder[A] = JsonFieldEncoder[B].contramap(_.coerce[B]) }