Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation and examples #158

Merged
merged 64 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
6ad4b2b
added basic documentation with example
domdorn Nov 6, 2021
1a27002
added more dependencies to docs
domdorn Nov 7, 2021
b390830
incorporated feedback by @thinkharderdev
domdorn Nov 7, 2021
968eff2
fixed wording 'ZIO-Schema' -> 'ZIO Schema'
domdorn Nov 7, 2021
fde9fe7
fixed naming of other zio libraries
domdorn Nov 7, 2021
d8600bd
fix sbt publish setting
domdorn Nov 7, 2021
b7dbc34
added examples subproject
domdorn Nov 7, 2021
a672670
docs: fixed mdoc link and added version placeholder in overview/index.md
domdorn Nov 8, 2021
e8ae8be
docs: incorporated suggestions by @TobiasPfeifer
domdorn Nov 8, 2021
2267eee
scalafmt for build.sbt
domdorn Nov 9, 2021
0383cea
incorporated suggestions by @thinkharderdev
domdorn Nov 18, 2021
c8383da
Support for annotations on all types (#147)
alexvanolst Nov 8, 2021
af86c1d
Provide direct support for Map (#142)
pierangeloc Nov 14, 2021
860d771
Add defaultValue to Schema (#80)
IMax153 Nov 15, 2021
77dc189
first commit
domdorn Nov 6, 2021
c724af6
[zio-schema-examples] sbt setup
domdorn Nov 6, 2021
cc2470c
[zio-schema-examples] readme init
domdorn Nov 6, 2021
89c7ff9
[zio-schema-examples] example 1
domdorn Nov 6, 2021
052f385
[zio-schema-examples] example 2
domdorn Nov 6, 2021
fbadb8e
[zio-schema-examples] example 3 (WIP)
domdorn Nov 6, 2021
1ef5561
[zio-schema-examples] example 3
domdorn Nov 6, 2021
0d4045c
[zio-schema-examples] Example3: Don't share domain with other samples
domdorn Nov 6, 2021
5ec9be7
[zio-schema-examples] Example4 transforming DTOs
domdorn Nov 6, 2021
cd24ba3
[zio-schema-examples] Example5 diffing
domdorn Nov 6, 2021
685c161
[zio-schema-examples] example 4: fixed map/flatmap in example
domdorn Nov 6, 2021
a14820e
[zio-schema-examples] example 4: another try to converting DTOs
domdorn Nov 6, 2021
718dff8
[zio-schema-examples] example 6 reified optics stub
domdorn Nov 6, 2021
e56b9fd
[zio-schema-examples] example 6 reified optics examples
domdorn Nov 7, 2021
b4d3524
[zio-schema-examples] example 1 + 2: schema fixes for newest zio-schema
domdorn Nov 7, 2021
21d1af1
[zio-schema-examples] Problem 7: Initial code
domdorn Nov 7, 2021
7287dba
[zio-schema-examples] Example 6: adding employee now works
domdorn Nov 7, 2021
f619ac4
[zio-schema-examples] Example 7: added notes on performance requirements
domdorn Nov 7, 2021
30ee961
[zio-schema-examples] Example 7: added parameter list to methods, fix…
domdorn Nov 7, 2021
797dded
[zio-schema-examples] Example 7: added Person and Profile schema as i…
domdorn Nov 7, 2021
daadf1a
[zio-schema-examples] Example 7: renamed method for viewing, added Ru…
domdorn Nov 7, 2021
96f83d3
[zio-schema-examples] Example 7: sketched toDynamicValue method
domdorn Nov 7, 2021
a0c457f
[zio-schema-examples] Example 7: implemented toDynamicValue method
domdorn Nov 7, 2021
2385454
[zio-schema-examples] Example 7: primitive impl of decode using toDV
domdorn Nov 7, 2021
b6dfdb9
[zio-schema-examples] Example 7: produce multiple solutions, pick wor…
domdorn Nov 7, 2021
5ed01d8
[zio-schema-examples] Example 7: introduce QueryParam type alias and …
domdorn Nov 7, 2021
0e5fafa
[zio-schema-examples] Example 7: return static function on error case
domdorn Nov 7, 2021
8590408
[zio-schema-examples] Example 7: initial impl of Primitive(standardtype)
domdorn Nov 7, 2021
325341c
[zio-schema-examples] Example 7: implemented fail
domdorn Nov 7, 2021
7dd13fa
[zio-schema-examples] Example 7: simple impl of lazy
domdorn Nov 7, 2021
b24db33
[zio-schema-examples] Example 7: better lazy impl with `lazy val`
domdorn Nov 7, 2021
1ce30df
[zio-schema-examples] Example 7: impl of Meta
domdorn Nov 7, 2021
9469c75
[zio-schema-examples] Example 7: impl of CaseClass1
domdorn Nov 7, 2021
4470d7f
[zio-schema-examples] Example 7: impl of CaseClass2
domdorn Nov 7, 2021
a5f7aea
[zio-schema-examples] Example 7: impl of CaseClass3
domdorn Nov 7, 2021
f15b44f
[zio-schema-examples] Example 7: extracted compiler to builder
domdorn Nov 7, 2021
043ee19
[zio-schema-examples] Example 7: implemented Transform
domdorn Nov 7, 2021
e39f2b6
[zio-schema-examples] * Example for an Encoder and Decoder using the …
calvinlfer Nov 22, 2021
4ef1822
revert local changes
domdorn Nov 30, 2021
8aafd6e
moved sources to appropriate place
domdorn Nov 30, 2021
71281ab
fixed example
domdorn Nov 30, 2021
12c13b8
[zio-schema-examples] reverted changes to build.sbt
domdorn Nov 30, 2021
8bfd80f
Merge branch 'main' into docs
domdorn Nov 30, 2021
5320e65
[zio-schema-examples] removed additional build.sbt, fixed problems in…
domdorn Nov 30, 2021
38d20e5
[zio-schema-examples] scalaFmt applied
domdorn Dec 1, 2021
68a9ce3
Fix build for scala 2.12 and apply linter
thinkharderdev Dec 8, 2021
cca453e
Merge branch 'main' into docs
thinkharderdev Dec 8, 2021
71d90b5
Fix compilation errors for scala 2.12
thinkharderdev Dec 13, 2021
6a633ed
Merge branch 'main' into docs
thinkharderdev Dec 14, 2021
b65bc52
Unused imports
thinkharderdev Dec 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ _ZIO Schema_ is a [ZIO](https://zio.dev)-based library for modeling the schema o
With schema descriptions that can be automatically derived for case classes and sealed traits, _ZIO Schema_ provide powerful features for free:

- Codecs for any supported protocol (JSON, protobuf, etc.), so data structures can be serialized and deserialized in a principled way
- Diffing, patching, merging, and other generic-data-based operations (_TODO_)
- Migration of data structures from one schema to another compatible schema (_TODO_)
- Derivation of arbitrary type classes (`Eq`, `Show`, `Ord`, etc.) from the structure of the data (_TODO_)
- Diffing, patching, merging, and other generic-data-based operations
- Migration of data structures from one schema to another compatible schema
- Derivation of arbitrary type classes (`Eq`, `Show`, `Ord`, etc.) from the structure of the data

When your data structures need to be serialized, deserialized, persisted, or transported across the wire, then _ZIO Schema_ lets you focus on data modeling and automatically tackle all the low-level, messy details for you.

Expand All @@ -22,7 +22,12 @@ _ZIO Schema_ is used by a growing number of ZIO libraries, including _ZIO Flow_,
Add in your `build.sbt`:

```scala
libraryDependencies += "dev.zio" %% "zio-schema" % "<version>"
libraryDependencies ++= Seq(
"dev.zio" %% "zio-schema" % "<version>",
// Required for automatic generic derivation of schemas
"dev.zio" %% "zio-schema-derivation" % "<version>",
"org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided"
)
```

[Badge-CI]: https://github.com/zio/zio-schema/workflows/CI/badge.svg
Expand Down
23 changes: 21 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ lazy val root = project
.in(file("."))
.settings(
name := "zio-schema",
publish / skip := true,
unusedCompileDependenciesFilter -= moduleFilter("org.scala-js", "scalajs-library")
publish / skip := true
// unusedCompileDependenciesFilter -= moduleFilter("org.scala-js", "scalajs-library")
)
.aggregate(
zioSchemaJVM,
Expand All @@ -62,6 +62,8 @@ lazy val root = project
zioSchemaOpticsJVM,
zioSchemaProtobufJS,
zioSchemaProtobufJVM,
zioSchemaExamplesJS,
zioSchemaExamplesJVM,
testsJVM,
testsJS,
zioSchemaZioTestJVM,
Expand Down Expand Up @@ -181,6 +183,23 @@ lazy val zioSchemaOpticsJS = zioSchemaOptics.js
lazy val zioSchemaOpticsJVM = zioSchemaOptics.jvm
.settings(Test / fork := true)

lazy val zioSchemaExamples = crossProject(JSPlatform, JVMPlatform)
.in(file("zio-schema-examples"))
.settings(stdSettings("zio-schema-examples"))
.settings(crossScalaVersions -= Scala212)
.dependsOn(zioSchema, zioSchemaJson, zioSchemaProtobuf, zioSchemaOptics)
.settings(
publish / skip := true,
moduleName := "zio-schema-example",
scalacOptions -= "-Yno-imports",
scalacOptions -= "-Xfatal-warnings"
)

lazy val zioSchemaExamplesJS = zioSchemaExamples.js
.settings(scalaJSUseMainModuleInitializer := true)

lazy val zioSchemaExamplesJVM = zioSchemaExamples.jvm

lazy val zioSchemaZioTest = crossProject(JSPlatform, JVMPlatform)
.in(file("zio-schema-zio-test"))
.dependsOn(zioSchema, zioSchemaDerivation, tests % "test->test")
Expand Down
203 changes: 203 additions & 0 deletions docs/overview/first_schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
---
id: first_schema
title: "Your first ZIO Schema"
---
## Your First ZIO Schema

ZIO Schema provides macros to help you create `Schema`s out of your data types. But before using the macros,
we should take a look at how to do this the manual way.

### The Domain
Like in [Overview](index.md), we define our example domain like this:

```scala
object Domain {
final case class Person(name: String, age: Int)

sealed trait PaymentMethod

object PaymentMethod {
final case class CreditCard(number: String, expirationMonth: Int, expirationYear: Int) extends PaymentMethod
final case class WireTransfer(accountNumber: String, bankCode: String) extends PaymentMethod
}

final case class Customer(person: Person, paymentMethod: PaymentMethod)

}
```

### Manual construction of a Schema

This part is similar to other libraries that you might know, e.g. for JSON processing.
Basically, you create a `Schema` for every data type in your domain:

```scala

object ManualConstruction {
import zio.schema.Schema._
import Domain._
import Domain.PaymentMethod._

val schemaPerson: Schema[Person] = Schema.CaseClass2[String, Int, Person](
field1 = Schema.Field[String]("name", Schema.primitive[String]),
field2 = Schema.Field[Int]("age", Schema.primitive[Int]),
construct = (name, age) => Person(name, age),
extractField1 = p => p.name,
extractField2 = p => p.age
)

val schemaPaymentMethodWireTransfer: Schema[WireTransfer] = Schema.CaseClass2[String, String, WireTransfer](
field1 = Schema.Field[String]("accountNumber", Schema.primitive[String]),
field2 = Schema.Field[String]("bankCode", Schema.primitive[String]),
construct = (number, bankCode) => PaymentMethod.WireTransfer(number, bankCode),
extractField1 = p => p.accountNumber,
extractField2 = p => p.bankCode
)

val schemaPaymentMethodCreditCard: Schema[CreditCard] = Schema.CaseClass3[String, Int, Int, CreditCard](
field1 = Schema.Field[String]("number", Schema.primitive[String]),
field2 = Schema.Field[Int]("expirationMonth", Schema.primitive[Int]),
field3 = Schema.Field[Int]("expirationYear", Schema.primitive[Int]),
construct = (number, expirationMonth, expirationYear) => PaymentMethod.CreditCard(number, expirationMonth, expirationYear),
extractField1 = p => p.number,
extractField2 = p => p.expirationMonth,
extractField3 = p => p.expirationYear
)

val schemaPaymentMethod: Schema[PaymentMethod] = Schema.Enum2(
case1 = Case[PaymentMethod.CreditCard, PaymentMethod](
id = "CreditCard",
codec = schemaPaymentMethodCreditCard,
unsafeDeconstruct = pm => pm.asInstanceOf[PaymentMethod.CreditCard]
),
case2 = Case[PaymentMethod.WireTransfer, PaymentMethod](
id = "WireTransfer",
codec = schemaPaymentMethodWireTransfer,
unsafeDeconstruct = pm => pm.asInstanceOf[PaymentMethod.WireTransfer]
)
)

val schemaCustomer: Schema[Customer] = Schema.CaseClass2[Person, PaymentMethod, Customer](
field1 = Schema.Field[Person]("person", schemaPerson),
field2 = Schema.Field[PaymentMethod]("paymentMethod", schemaPaymentMethod),
construct = (person, paymentMethod) => Customer(person, paymentMethod),
extractField1 = c => c.person,
extractField2 = c => c.paymentMethod
)
}

```

### Macro derivation
Using macros, the above code gets reduced to this:

```scala

object MacroConstruction {
import Domain._

val schemaPerson: Schema[Person] = DeriveSchema.gen[Person]

val schemaPaymentMethod: Schema[PaymentMethod] = DeriveSchema.gen[PaymentMethod]

val schemaCustomer: Schema[Customer] = DeriveSchema.gen[Customer]
}
```

## Applying it to our domain

### Json example
Lets put this all together in a small sample:
```scala
object JsonSample extends zio.App {
import zio.schema.codec.JsonCodec
import ManualConstruction._
import zio.stream.ZStream

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = for {
_ <- ZIO.unit
person = Person("Michelle", 32)
personToJsonTransducer = JsonCodec.encoder[Person](schemaPerson)
_ <- ZStream(person)
.transduce(personToJsonTransducer)
.transduce(ZTransducer.utf8Decode)
.foreach(ZIO.debug)
} yield ExitCode.success
}
```

When we run this, we get our expected result printed out:
```json
{"name":"Michelle","age":32}
```

### Protobuf example

```scala
object ProtobufExample extends zio.App {
import zio.schema.codec.ProtobufCodec
import ManualConstruction._
import zio.stream.ZStream

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = for {
_ <- ZIO.unit
_ <- ZIO.debug("protobuf roundtrip")
person = Person("Michelle", 32)

personToProto = ProtobufCodec.encoder[Person](schemaPerson)
protoToPerson = ProtobufCodec.decoder[Person](schemaPerson)

newPerson <- ZStream(person)
.transduce(personToProto)
.transduce(protoToPerson)
.runHead
.some
.catchAll(error => ZIO.debug(error))
_ <- ZIO.debug("is old person the new person? " + (person == newPerson).toString)
_ <- ZIO.debug("old person: " + person)
_ <- ZIO.debug("new person: " + newPerson)
} yield ExitCode.success
}
```


### Combining different encoders
Let's take a look at a roundtrip converting an object to JSON and back, then converting it to a protobuf and back.
This is a simple example, but it shows how to combine different encoders to achieve a roundtrip.

```scala
object CombiningExample extends zio.App {
import zio.schema.codec.JsonCodec
import zio.schema.codec.ProtobufCodec
import ManualConstruction._
import zio.stream.ZStream

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = for {
_ <- ZIO.unit
_ <- ZIO.debug("combining roundtrip")
person = Person("Michelle", 32)

personToJson = JsonCodec.encoder[Person](schemaPerson)
jsonToPerson = JsonCodec.decoder[Person](schemaPerson)

personToProto = ProtobufCodec.encoder[Person](schemaPerson)
protoToPerson = ProtobufCodec.decoder[Person](schemaPerson)

newPerson <- ZStream(person)
.tap(v => ZIO.debug("input object is: " + v))
.transduce(personToJson)
.transduce(jsonToPerson)
.tap(v => ZIO.debug("object after json roundtrip: " + v))
.transduce(personToProto)
.transduce(protoToPerson)
.tap(v => ZIO.debug("person after protobuf roundtrip: " + v))
.runHead
.some
.catchAll(error => ZIO.debug(error))
_ <- ZIO.debug("is old person the new person? " + (person == newPerson).toString)
_ <- ZIO.debug("old person: " + person)
_ <- ZIO.debug("new person: " + newPerson)
} yield ExitCode.success
}
```

53 changes: 50 additions & 3 deletions docs/overview/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,55 @@ id: overview_index
title: "Contents"
---

TODO: List of contents available

## Installation

TODO: Installation details
Add in your `build.sbt`:

```scala
libraryDependencies += "dev.zio" %% "zio-schema" % "@RELEASE_VERSION@"
libraryDependencies += "dev.zio" %% "zio-schema-json" % "@RELEASE_VERSION@"
libraryDependencies += "dev.zio" %% "zio-schema-protobuf" % "@RELEASE_VERSION@"
```

## Purpose of ZIO Schema
ZIO Schema allows you to create representations of your data types as values.

Once you have a representation of your data types, you can use it to
- serialize and deserialize your types
- validate your types
- transform your types
- create instances of your types

You can then use one of the various codecs (or create your own) to serialize and deserialize your types.

Example of possible codecs are:
- CSV Codec
- JSON Codec (already available)
- Apache Avro Codec (in progress)
- Apache Thrift Codec (in progress)
- XML Codec
- YAML Codec
- Protobuf Codec (already available)
- QueryString Codec
- etc.

Example use cases that are possible:
- Serializing and deserializing JSON
- Serializing and deserializing XML
- Validating JSON
- Validating XML
- Transforming JSON
- Transforming XML
- Transforming JSON to XML
- Transforming XML to JSON
- Creating diffs from arbitrary data structures
- Creating migrations / evolutions e.g. of Events used in Event-Sourcing
- Transformation pipelines, e.g.
1. convert from protobuf to object, e.g. `PersonDTO`,
2. transform to another representation, e.g. `Person`,
3. validate
4. transform to JSON `JsonObject`
5. serialize to `String`



Loading