diff --git a/README.md b/README.md
index 171044685..a36948f88 100644
--- a/README.md
+++ b/README.md
@@ -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" % "0.6.2"
+libraryDependencies += "dev.zio" %% "zio-json" % "0.7.3"
```
## Example
@@ -50,15 +50,21 @@ into a Scala `case class`
case class Banana(curvature: Double)
```
-To do this, we create an *instance* of the `JsonDecoder` typeclass for `Banana` using the `zio-json` code generator. It is best practice to put it on the companion of `Banana`, like so
+To do this, we derive an *instance* of the `JsonDecoder` typeclass for `Banana`.
```scala
-object Banana {
- implicit val decoder: JsonDecoder[Banana] = DeriveJsonDecoder.gen[Banana]
-}
+case class Banana(curvature: Double) derives JsonDecoder
```
-_Note: If you’re using Scala 3 and your case class is defining default parameters, `-Yretain-trees` needs to be added to `scalacOptions`._
+> [!NOTE]
+>
+> In scala 2, we need to use the `zio-json` code generator. It is best practice to put it on the companion of `Banana`, like so
+>
+> ```scala
+> object Banana {
+> implicit val decoder: JsonDecoder[Banana] = DeriveJsonDecoder.gen[Banana]
+> }
+> ```
Now we can parse JSON into our object
@@ -67,13 +73,10 @@ scala> """{"curvature":0.5}""".fromJson[Banana]
val res: Either[String, Banana] = Right(Banana(0.5))
```
-Likewise, to produce JSON from our data we define a `JsonEncoder`
+Likewise, to produce JSON from our data we derive a `JsonEncoder`
```scala
-object Banana {
- ...
- implicit val encoder: JsonEncoder[Banana] = DeriveJsonEncoder.gen[Banana]
-}
+case class Banana(curvature: Double) derives JsonEncoder
scala> Banana(0.5).toJson
val res: String = {"curvature":0.5}
@@ -85,6 +88,16 @@ val res: String =
}
```
+> [!NOTE]
+>
+> In scala 2:
+> ```scala
+> object Banana {
+> ...
+> implicit val encoder: JsonEncoder[Banana] = DeriveJsonEncoder.gen[Banana]
+> }
+> ```
+
And bad JSON will produce an error in `jq` syntax with an additional piece of contextual information (in parentheses)
```
@@ -95,20 +108,49 @@ val res: Either[String, Banana] = Left(.curvature(expected a number, got w))
Say we extend our data model to include more data types
```scala
-sealed trait Fruit
-case class Banana(curvature: Double) extends Fruit
-case class Apple (poison: Boolean) extends Fruit
+enum Fruit:
+ case Banana(curvature: Double) extends Fruit
+ case Apple(poison: Boolean) extends Fruit
```
-we can generate the encoder and decoder for the entire `sealed` family
+we can generate the encoder and decoder for the entire `sealed` family using `JsonCodec`
```scala
-object Fruit {
- implicit val decoder: JsonDecoder[Fruit] = DeriveJsonDecoder.gen[Fruit]
- implicit val encoder: JsonEncoder[Fruit] = DeriveJsonEncoder.gen[Fruit]
-}
+enum Fruit derives JsonCodec:
+ case Banana(curvature: Double)
+ case Apple(poison: Boolean)
```
+> [!NOTE]
+>
+> In scala 2:
+>
+> ```scala mdoc:compile-only
+> import zio.json._
+>
+> sealed trait Fruit extends Product with Serializable
+> case class Banana(curvature: Double) extends Fruit
+> case class Apple(poison: Boolean) extends Fruit
+>
+> object Fruit {
+> implicit val decoder: JsonDecoder[Fruit] =
+> DeriveJsonDecoder.gen[Fruit]
+>
+> implicit val encoder: JsonEncoder[Fruit] =
+> DeriveJsonEncoder.gen[Fruit]
+> }
+>
+> val json1 = """{ "Banana":{ "curvature":0.5 }}"""
+> val json2 = """{ "Apple": { "poison": false }}"""
+> val malformedJson = """{ "Banana":{ "curvature": true }}"""
+>
+> json1.fromJson[Fruit]
+> json2.fromJson[Fruit]
+> malformedJson.fromJson[Fruit]
+>
+> List(Apple(false), Banana(0.4)).toJsonPretty
+> ```
+
allowing us to load the fruit based on a single field type tag in the JSON
```
@@ -122,19 +164,13 @@ val res: Either[String, Fruit] = Right(Apple(false))
Almost all of the standard library data types are supported as fields on the case class, and it is easy to add support if one is missing.
```scala
-import zio.json._
+import zio.json.*
-sealed trait Fruit extends Product with Serializable
-case class Banana(curvature: Double) extends Fruit
-case class Apple(poison: Boolean) extends Fruit
+enum Fruit extends Product, Serializable derives JsonCodec:
+ case Banana(curvature: Double) extends Fruit
+ case Apple(poison: Boolean) extends Fruit
-object Fruit {
- implicit val decoder: JsonDecoder[Fruit] =
- DeriveJsonDecoder.gen[Fruit]
-
- implicit val encoder: JsonEncoder[Fruit] =
- DeriveJsonEncoder.gen[Fruit]
-}
+export Fruit.*
val json1 = """{ "Banana":{ "curvature":0.5 }}"""
val json2 = """{ "Apple": { "poison": false }}"""
diff --git a/docs/index.md b/docs/index.mdx
similarity index 71%
rename from docs/index.md
rename to docs/index.mdx
index 205c70050..9e465423a 100644
--- a/docs/index.md
+++ b/docs/index.mdx
@@ -4,6 +4,9 @@ title: "Getting Started with ZIO Json"
sidebar_label: "Getting Started"
---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
[ZIO Json](https://github.com/zio/zio-json) is a fast and secure JSON library with tight ZIO integration.
@PROJECT_BADGES@
@@ -34,10 +37,23 @@ Let's try a simple example of encoding and decoding JSON using ZIO JSON.
All the following code snippets assume that the following imports have been declared
+
+
+
```scala
import zio.json._
```
+
+
+
+```scala
+import zio.json.*
+```
+
+
+
+
Say we want to be able to read some JSON like
```json
@@ -50,6 +66,9 @@ into a Scala `case class`
case class Banana(curvature: Double)
```
+
+
+
To do this, we create an *instance* of the `JsonDecoder` typeclass for `Banana` using the `zio-json` code generator. It is best practice to put it on the companion of `Banana`, like so
```scala
@@ -58,7 +77,19 @@ object Banana {
}
```
-_Note: If you’re using Scala 3 and your case class is defining default parameters, `-Yretain-trees` needs to be added to `scalacOptions`._
+
+
+
+To do this, we derive an *instance* of the `JsonDecoder` typeclass for `Banana`.
+
+```scala
+case class Banana(curvature: Double) derives JsonDecoder
+```
+
+Note: If your case class is defining default parameters, -Yretain-trees needs to be added to scalacOptions.
+
+
+
Now we can parse JSON into our object
@@ -67,14 +98,29 @@ scala> """{"curvature":0.5}""".fromJson[Banana]
val res: Either[String, Banana] = Right(Banana(0.5))
```
-Likewise, to produce JSON from our data we define a `JsonEncoder`
+Likewise, to produce JSON from our data we derive a `JsonEncoder`
+
+
+
```scala
object Banana {
...
implicit val encoder: JsonEncoder[Banana] = DeriveJsonEncoder.gen[Banana]
}
+```
+
+
+
+
+```scala
+case class Banana(curvature: Double) derives JsonEncoder
+```
+
+
+
+```
scala> Banana(0.5).toJson
val res: String = {"curvature":0.5}
@@ -94,14 +140,32 @@ val res: Either[String, Banana] = Left(.curvature(expected a number, got w))
Say we extend our data model to include more data types
+
+
+
```scala
sealed trait Fruit
case class Banana(curvature: Double) extends Fruit
case class Apple (poison: Boolean) extends Fruit
```
+
+
+
+```scala
+enum Fruit:
+ case Banana(curvature: Double) extends Fruit
+ case Apple (poison: Boolean) extends Fruit
+```
+
+
+
+
we can generate the encoder and decoder for the entire `sealed` family
+
+
+
```scala
object Fruit {
implicit val decoder: JsonDecoder[Fruit] = DeriveJsonDecoder.gen[Fruit]
@@ -109,6 +173,18 @@ object Fruit {
}
```
+
+
+
+```scala
+enum Fruit derives JsonCodec:
+ case Banana(curvature: Double)
+ case Apple (poison: Boolean)
+```
+
+
+
+
allowing us to load the fruit based on a single field type tag in the JSON
```
@@ -121,6 +197,9 @@ val res: Either[String, Fruit] = Right(Apple(false))
Almost all of the standard library data types are supported as fields on the case class, and it is easy to add support if one is missing.
+
+
+
```scala mdoc:compile-only
import zio.json._
@@ -147,6 +226,32 @@ malformedJson.fromJson[Fruit]
List(Apple(false), Banana(0.4)).toJsonPretty
```
+
+
+
+```scala
+import zio.json.*
+
+enum Fruit extends Product, Serializable derives JsonCodec:
+ case Banana(curvature: Double) extends Fruit
+ case Apple(poison: Boolean) extends Fruit
+
+export Fruit.*
+
+val json1 = """{ "Banana":{ "curvature":0.5 }}"""
+val json2 = """{ "Apple": { "poison": false }}"""
+val malformedJson = """{ "Banana":{ "curvature": true }}"""
+
+json1.fromJson[Fruit]
+json2.fromJson[Fruit]
+malformedJson.fromJson[Fruit]
+
+List(Apple(false), Banana(0.4)).toJsonPretty
+```
+
+
+
+
# How
Extreme **performance** is achieved by decoding JSON directly from the input source into business objects (inspired by [plokhotnyuk](https://github.com/plokhotnyuk/jsoniter-scala)). Although not a requirement, the latest advances in [Java Loom](https://wiki.openjdk.java.net/display/loom/Main) can be used to support arbitrarily large payloads with near-zero overhead.