Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
plokhotnyuk committed Nov 23, 2024
1 parent 870002c commit c66763f
Show file tree
Hide file tree
Showing 21 changed files with 95 additions and 83 deletions.
2 changes: 0 additions & 2 deletions docs/how-tos/1-how-to-double-check-safety-and-correctness.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
- Check if some security sensitive options of compile-time and runtime configuration are safe for your use cases
- Print and analyze sources of generated codecs (check number of anonymous classes, size of generated methods, etc.)
- Patch jsoniter-scala sources with some instrumentation, build and publish locally (as example to check number of instantiated codecs)

Challenge: Find a probable correctness or security flaw and submit a bug issue to jsoniter-scala project
2 changes: 0 additions & 2 deletions docs/how-tos/2-how-to-squize-more-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,3 @@ Options to consider:
Anti-patterns:
- Generation of codecs for intermediate (non-top level) data structures (as an example, overuse of `derives` keyword)
- Generation and wide usage of codecs for primitives, strings, etc.

Challenge: Print generated codecs and patch them for yet more efficiency, then open an improvement issue in the jsoniter-scala project
2 changes: 0 additions & 2 deletions docs/how-tos/3-how-to-reduce-maintenance-costs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,3 @@ Approaches to consider:
- Use 2 data models for huge projects with different API versions or 3-rd party data structures (use chimney or ducktape for transformation between them)
- Use GraphQL (caliban) for reach and highly customized requests
- Use Smithy (smithy4s-json) for model first approach with cross-language APIs

Challenge: Use Dependents side section of the https://index.scala-lang.org/plokhotnyuk/jsoniter-scala page to discover and try some other integrations with jsoniter-scala
Original file line number Diff line number Diff line change
@@ -1 +1 @@
api-key signing
Example: api-key signing
Original file line number Diff line number Diff line change
@@ -1 +1 @@
OpenRTB native
Example: OpenRTB native
2 changes: 1 addition & 1 deletion docs/how-tos/6-how-to-validate-schemaless-JSON.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
jsontier-scala-examples/example_02.sc
Example: jsontier-scala-examples/example_02.sc
2 changes: 0 additions & 2 deletions docs/how-tos/7-how-to-parse-and-serialize-schemaless-JSON.md
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
dijon, jsoniter-scala-circe, play-json-jsoniter

Challenge: Provide a PR with adding support of Scala 3 for dijon project
13 changes: 6 additions & 7 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@
- Performance
- Productivity

Using `scala-cli` (or `scala` for latest versions of Scala 3):
2. Features

2. Tutorials
3. Tutorials

3. How-tos
4. How-tos

4. API docs
5. API docs
https://www.javadoc.io/doc/com.github.plokhotnyuk.jsoniter-scala

5. Features

6. Known-issues

7. Explanations
7. Blog posts
51 changes: 23 additions & 28 deletions docs/tutorials/1-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,15 @@ enum OrderStatus extends Enum[OrderStatus]:

case class OrderItem(product: Product, quantity: Int)

case class Order(id: Long, customer: Customer, items: List[OrderItem], status: OrderStatus)
case class Order(id: Long, customer: Customer, items: Seq[OrderItem], status: OrderStatus)

case class Customer(id: Long, name: String, email: String, address: Address)

case class Address(street: String, city: String, state: String, zip: String)

enum PaymentType extends Enum[PaymentType]:
case CreditCard, PayPal

case class PaymentMethod(`type`: PaymentType, details: Map[String, String]/*e.g. card number, expiration date*/)
enum PaymentMethod:
case CreditCard(cardNumber: Long, validThru: java.time.YearMonth) extends PaymentMethod
case PayPal(id: String) extends PaymentMethod

case class Payment(method: PaymentMethod, amount: BigDecimal, timestamp: java.time.Instant)

Expand Down Expand Up @@ -107,7 +106,7 @@ val customer2 = Customer(
val order1 = Order(
id = 1L,
customer = customer1,
items = List(
items = Seq(
OrderItem(product1, 1),
OrderItem(product2, 2)
),
Expand All @@ -116,23 +115,17 @@ val order1 = Order(
val order2 = Order(
id = 2L,
customer = customer2,
items = List(
items = Seq(
OrderItem(product3, 1)
),
status = OrderStatus.Shipped
)
val paymentMethod1 = PaymentMethod(
`type` = PaymentType.CreditCard,
details = Map(
"card_number" -> "1234-5678-9012-3456",
"expiration_date" -> "12/2026"
)
val paymentMethod1 = PaymentMethod.CreditCard(
cardNumber = 1234_5678_9012_3456L,
validThru = java.time.YearMonth.parse("2026-12")
)
val paymentMethod2 = PaymentMethod(
`type` = PaymentType.PayPal,
details = Map(
"paypal_id" -> "[email protected]"
)
val paymentMethod2 = PaymentMethod.PayPal(
id = "[email protected]"
)
val payment1 = Payment(
method = paymentMethod1,
Expand All @@ -152,26 +145,27 @@ val orderPayment2 = OrderPayment(
order = order2,
payment = payment2
)
val report = List(
val report = Seq(
orderPayment1,
orderPayment2
)
```

## Defining the codec

To derive a codec the report type (`List[OrderPayment]` type in our case) we will use `JsonCodecMaker.make` macros:
Now we need to derive a codec for the report type (`List[OrderPayment]` type in our case). We will use
`JsonCodecMaker.make` macros for that:
```scala
given JsonValueCodec[List[OrderPayment]] = JsonCodecMaker.make
given JsonValueCodec[Seq[OrderPayment]] = JsonCodecMaker.make
```

An instance of this codec (also known as a type-class instance) is getting to be visible in the scope of subsequent
calls of parsing and serialization methods.
calls of parsing and serialization methods.

## Serialization

Now we are ready to serialize the report. Just need to define some entry point method and call `writeToString`.
We will also print resulting JSON to the system output to see it as a process output:
Now we are ready to serialize the report. For that we need to define some entry point method and call `writeToString`.
We will also print resulting JSON to the system output to see it as an output:

```scala
@main def gettingStarted: Unit =
Expand All @@ -190,13 +184,14 @@ Having the JSON string in memory you can parse it using following lines that sho
println(parsedReport)
```

Now you can rerun the script and get additionally printed `toString` representation of a report parsed from JSON string.
Let's rerun the script and get additionally printed `toString` representation of a report parsed from JSON string.

If something gone wrong you can pick the final version of [a script for this tutorial](1-getting-started.scala) and then run it.
If something gone wrong you can pick and run [the final version of a script for this tutorial](1-getting-started.scala).

## Challenge
Experiment with different types of collections and try to find any collection type from the standard Scala library that
is not supported by `JsonCodecMaker.make` macros to derive codec for serialization *and* parsing.
Experiment with the script to use different types of collections instead of `Seq` and try to find any collection type
from the standard Scala library that is not supported by `JsonCodecMaker.make` macros to derive codec for serialization
and parsing.

## Recap
In this tutorial we learned basics for parsing and serialization of complex nested data structures using `scala-cli`.
Expand Down
33 changes: 13 additions & 20 deletions docs/tutorials/1-getting-started.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ enum OrderStatus extends Enum[OrderStatus]:

case class OrderItem(product: Product, quantity: Int)

case class Order(id: Long, customer: Customer, items: List[OrderItem], status: OrderStatus)
case class Order(id: Long, customer: Customer, items: Seq[OrderItem], status: OrderStatus)

case class Customer(id: Long, name: String, email: String, address: Address)

case class Address(street: String, city: String, state: String, zip: String)

enum PaymentType extends Enum[PaymentType]:
case CreditCard, PayPal

case class PaymentMethod(`type`: PaymentType, details: Map[String, String]/*e.g. card number, expiration date*/)
enum PaymentMethod:
case CreditCard(cardNumber: Long, validThru: java.time.YearMonth) extends PaymentMethod
case PayPal(id: String) extends PaymentMethod

case class Payment(method: PaymentMethod, amount: BigDecimal, timestamp: java.time.Instant)

Expand Down Expand Up @@ -76,7 +75,7 @@ val customer2 = Customer(
val order1 = Order(
id = 1L,
customer = customer1,
items = List(
items = Seq(
OrderItem(product1, 1),
OrderItem(product2, 2)
),
Expand All @@ -85,23 +84,17 @@ val order1 = Order(
val order2 = Order(
id = 2L,
customer = customer2,
items = List(
items = Seq(
OrderItem(product3, 1)
),
status = OrderStatus.Shipped
)
val paymentMethod1 = PaymentMethod(
`type` = PaymentType.CreditCard,
details = Map(
"card_number" -> "1234-5678-9012-3456",
"expiration_date" -> "12/2026"
)
val paymentMethod1 = PaymentMethod.CreditCard(
cardNumber = 1234_5678_9012_3456L,
validThru = java.time.YearMonth.parse("2026-12")
)
val paymentMethod2 = PaymentMethod(
`type` = PaymentType.PayPal,
details = Map(
"paypal_id" -> "[email protected]"
)
val paymentMethod2 = PaymentMethod.PayPal(
id = "[email protected]"
)
val payment1 = Payment(
method = paymentMethod1,
Expand All @@ -121,12 +114,12 @@ val orderPayment2 = OrderPayment(
order = order2,
payment = payment2
)
val report = List(
val report = Seq(
orderPayment1,
orderPayment2
)

given JsonValueCodec[List[OrderPayment]] = JsonCodecMaker.make
given JsonValueCodec[Seq[OrderPayment]] = JsonCodecMaker.make

@main def gettingStarted: Unit =
val json = writeToString(report)
Expand Down
8 changes: 8 additions & 0 deletions docs/tutorials/2-use-compile-time-configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
1. CodecMakerConfiguration (renaming, stringification, enabling of recursion, disabling generation of decoding or encoding implementations, etc.)
2. Static annotations at field and class definitions and their priority over CodecMakerConfiguration

## Challenge
Experiment with different combinations of compile-time options and find those that are not supported.
Will compiler errors explain why codecs cannot be generated for such options?

## Recap
6 changes: 0 additions & 6 deletions docs/tutorials/2-use-runtime-configuration.md

This file was deleted.

4 changes: 0 additions & 4 deletions docs/tutorials/3-use-compile-time-configuration.md

This file was deleted.

11 changes: 11 additions & 0 deletions docs/tutorials/3-use-runtime-configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Examples with runtime configuration options for:
- Pretty printing and stack traces for debugging
- Max buffer sizes for safety when parsing from `java.io.InputStream` (or `java.nio.DirectByteBuffer`)
- Buffer sizes and disabling of exception hex dump for performance

## Challenge
Serialize the following string to JSON representation using `writeToString` and then convert resulting string to
byte array using some non UTF-8 charset and then parse it back using `readFromByteArray`. Will jsoniter-scala
parser throw an error with a helpful message?

## Recap
6 changes: 6 additions & 0 deletions docs/tutorials/4-derive-codecs-for-algebraic-data-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Scala 3 enums with case classes types
Compile-time configuration of discriminator encoding and mapping of type names

## Challenge

## Recap
7 changes: 7 additions & 0 deletions docs/tutorials/5-use-derives-keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Use inlined CodecMakerConfiguration
Use static annotations and their priority over CodecMakerConfiguration
Use derives on top-level data structures

## Challenge

## Recap
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Generate ~10GB JSON of streamed values
Parse and handle parsed data without loading the whole input in memory
Do the same with huge JSON array

## Challenge

## Recap
Empty file.
11 changes: 11 additions & 0 deletions docs/tutorials/7-write-custom-value-and-key-codecs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Examples:
1. Custom value codec for Base64
2. Custom value codec for CreditCardNumber
3. Custom value codec JS compatible `Long` values
4. Custom value codec for generic collections
5. Custom key codec for enums
6. Custom key codec for tuples

## Challenge

## Recap
4 changes: 0 additions & 4 deletions docs/tutorials/7-writing-custom-value-codecs.md

This file was deleted.

3 changes: 0 additions & 3 deletions docs/tutorials/8-writing-custom-key-codecs.md

This file was deleted.

0 comments on commit c66763f

Please sign in to comment.