@zio.dev/zio-blocks 0.0.32 → 0.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/guides/compile-time-resource-safety-with-scope.md +16 -17
  2. package/guides/getting-started-with-mux.md +1507 -0
  3. package/guides/query-dsl-extending.md +161 -102
  4. package/guides/query-dsl-fluent-builder.md +217 -157
  5. package/guides/query-dsl-reified-optics.md +12 -10
  6. package/guides/query-dsl-sql.md +246 -165
  7. package/guides/telemetry-guide.md +1069 -0
  8. package/guides/zio-schema-migration.md +29 -22
  9. package/index.md +293 -51
  10. package/package.json +1 -1
  11. package/plans/config-follow-up-prs.md +188 -0
  12. package/plans/config-pr-assessment-roadmap.md +310 -0
  13. package/reference/MuxDataFlow.jsx +250 -0
  14. package/reference/async.md +651 -0
  15. package/reference/chunk.md +3533 -308
  16. package/reference/codegen/case-class.md +436 -0
  17. package/reference/codegen/emitter-config.md +383 -0
  18. package/reference/codegen/examples.md +664 -0
  19. package/reference/codegen/field.md +316 -0
  20. package/reference/codegen/index.md +317 -0
  21. package/reference/codegen/scala-emitter.md +392 -0
  22. package/reference/codegen/scala-file.md +276 -0
  23. package/reference/codegen/sealed-trait.md +408 -0
  24. package/reference/codegen/type-definition.md +340 -0
  25. package/reference/codegen/type-ref.md +201 -0
  26. package/reference/combinators.md +347 -117
  27. package/reference/config.md +158 -0
  28. package/reference/context.md +4 -4
  29. package/reference/datastar.md +346 -0
  30. package/reference/docs.md +1461 -345
  31. package/reference/endpoint/auth-type.md +146 -0
  32. package/reference/endpoint/endpoint.md +297 -0
  33. package/reference/endpoint/http-codec.md +249 -0
  34. package/reference/endpoint/index.md +825 -0
  35. package/reference/endpoint/path-codec.md +237 -0
  36. package/reference/endpoint/route-pattern.md +196 -0
  37. package/reference/endpoint/route-tree.md +111 -0
  38. package/reference/endpoint/segment-codec.md +212 -0
  39. package/reference/html.md +1120 -0
  40. package/reference/htmx/attribute-values.md +359 -0
  41. package/reference/htmx/hx-encoding.md +111 -0
  42. package/reference/htmx/hx-params.md +204 -0
  43. package/reference/htmx/hx-swap.md +276 -0
  44. package/reference/htmx/hx-sync.md +251 -0
  45. package/reference/htmx/hx-target.md +314 -0
  46. package/reference/htmx/hx-trigger.md +457 -0
  47. package/reference/htmx/hx-url-update.md +239 -0
  48. package/reference/htmx/index.md +855 -0
  49. package/reference/http-model/index.md +47 -0
  50. package/reference/http-model/model.md +1481 -0
  51. package/reference/http-model/schema.md +747 -0
  52. package/reference/maybe.md +826 -0
  53. package/reference/media-type.md +2 -2
  54. package/reference/mux.mdx +823 -0
  55. package/reference/openapi.md +1351 -0
  56. package/reference/resource-management/defer-handle.md +1 -1
  57. package/reference/resource-management/resource.md +31 -2
  58. package/reference/resource-management/scope.md +28 -12
  59. package/reference/resource-management/wire.md +3 -7
  60. package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
  61. package/reference/ringbuffer/MpscDiagram.jsx +618 -0
  62. package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
  63. package/reference/ringbuffer/SpscDiagram.jsx +677 -0
  64. package/reference/ringbuffer/advanced.mdx +109 -0
  65. package/reference/ringbuffer/index.mdx +145 -0
  66. package/reference/ringbuffer/mpmc.mdx +151 -0
  67. package/reference/ringbuffer/mpsc.mdx +132 -0
  68. package/reference/ringbuffer/spmc.mdx +108 -0
  69. package/reference/ringbuffer/spsc.mdx +344 -0
  70. package/reference/{allows.md → schema/allows.md} +4 -4
  71. package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
  72. package/reference/{binding.md → schema/binding.md} +2 -3
  73. package/reference/schema/built-in-codecs/avro.md +451 -0
  74. package/reference/schema/built-in-codecs/bson.md +480 -0
  75. package/reference/schema/built-in-codecs/csv.md +564 -0
  76. package/reference/schema/built-in-codecs/index.md +77 -0
  77. package/reference/schema/built-in-codecs/json/index.md +295 -0
  78. package/reference/schema/built-in-codecs/json/json-config.md +217 -0
  79. package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +3 -3
  80. package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
  81. package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
  82. package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
  83. package/reference/schema/built-in-codecs/messagepack.md +508 -0
  84. package/reference/schema/built-in-codecs/thrift.md +433 -0
  85. package/reference/schema/built-in-codecs/toon.md +1078 -0
  86. package/reference/{xml.md → schema/built-in-codecs/xml.md} +34 -192
  87. package/reference/schema/built-in-codecs/yaml.md +552 -0
  88. package/reference/{codec.md → schema/codec.md} +10 -10
  89. package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +151 -5
  90. package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
  91. package/reference/schema/format.md +92 -0
  92. package/reference/schema/index.md +50 -0
  93. package/reference/schema/migration.md +297 -0
  94. package/reference/{modifier.md → schema/modifier.md} +58 -7
  95. package/reference/{optics.md → schema/optics.md} +2 -2
  96. package/reference/{patch.md → schema/patch.md} +1 -1
  97. package/{path-interpolator.md → reference/schema/path-interpolator.md} +165 -72
  98. package/reference/{schema-evolution → schema/schema-evolution}/as.md +5 -5
  99. package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
  100. package/reference/{schema-evolution → schema/schema-evolution}/into.md +3 -3
  101. package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
  102. package/reference/{schema.md → schema/schema.md} +13 -1
  103. package/reference/{structural-types.md → schema/structural-types.md} +1 -1
  104. package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
  105. package/reference/smithy.md +533 -0
  106. package/reference/sql/db-codec-deriver.md +71 -0
  107. package/reference/sql/db-codec.md +687 -0
  108. package/reference/sql/db-con.md +271 -0
  109. package/reference/sql/db-connection.md +153 -0
  110. package/reference/sql/db-param-writer.md +77 -0
  111. package/reference/sql/db-param.md +66 -0
  112. package/reference/sql/db-result-reader.md +146 -0
  113. package/reference/sql/db-tx.md +82 -0
  114. package/reference/sql/db-value.md +41 -0
  115. package/reference/sql/ddl.md +85 -0
  116. package/reference/sql/frag.md +254 -0
  117. package/reference/sql/index.md +341 -0
  118. package/reference/sql/repo.md +600 -0
  119. package/reference/sql/sql-dialect.md +73 -0
  120. package/reference/sql/sql-logger.md +62 -0
  121. package/reference/sql/sql-name-mapper.md +70 -0
  122. package/reference/sql/table-metadata.md +134 -0
  123. package/reference/sql/table.md +448 -0
  124. package/reference/sql/transactor-zio.md +399 -0
  125. package/reference/sql/transactor.md +353 -0
  126. package/reference/sql-zio.md +112 -0
  127. package/reference/streams/concurrent-operators.md +106 -0
  128. package/reference/streams/index.md +653 -0
  129. package/reference/streams/pipeline.md +718 -0
  130. package/reference/streams/reader.md +1284 -0
  131. package/reference/streams/scala-2-compatibility.md +55 -0
  132. package/reference/streams/sink.md +1426 -0
  133. package/reference/streams/stream.md +2526 -0
  134. package/reference/streams/writer.md +1045 -0
  135. package/reference/streams/zero-boxing.md +275 -0
  136. package/reference/telemetry.md +693 -0
  137. package/reference/typeid.md +2922 -583
  138. package/sidebars.js +238 -43
  139. package/superpowers/plans/2026-03-19-docs-critique-subagent.md +407 -0
  140. package/superpowers/specs/2026-03-19-docs-critique-subagent-design.md +222 -0
  141. package/reference/formats.md +0 -694
  142. package/reference/http-model.md +0 -1716
  143. package/reference/streams.md +0 -989
  144. package/ringbuffer.md +0 -249
  145. /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
  146. /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
  147. /package/reference/{lazy.md → schema/lazy.md} +0 -0
  148. /package/reference/{reflect.md → schema/reflect.md} +0 -0
  149. /package/reference/{registers.md → schema/registers.md} +0 -0
  150. /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
  151. /package/reference/{syntax.md → schema/syntax.md} +0 -0
  152. /package/reference/{validation.md → schema/validation.md} +0 -0
@@ -0,0 +1,322 @@
1
+ ---
2
+ id: json-selection
3
+ title: "JsonSelection"
4
+ ---
5
+
6
+ `JsonSelection` is a fluent wrapper type that enables composable, chainable navigation through JSON structures. It wraps `Either[SchemaError, Chunk[Json]]`, allowing operations that may fail gracefully or return multiple values.
7
+
8
+ ## Overview
9
+
10
+ `JsonSelection` makes it easy to navigate unknown or deeply nested JSON at runtime without needing to match on `Either` at each step. Chain operations like `JsonSelection#get`, `JsonSelection#apply`, `JsonSelection#filter`, and `JsonSelection#as` to build powerful queries.
11
+
12
+ **Key characteristics:**
13
+ - **Fluent chaining:** Operations chain naturally without unwrapping intermediate results
14
+ - **Multi-value support:** Can contain zero, one, or many `Json` values
15
+ - **Error propagation:** Errors short-circuit further operations; querying an error selection returns the same error
16
+ - **Type extraction:** Use `.as[Type]` to decode to Scala types with Schema-based derivation
17
+
18
+ ## Creating JsonSelection
19
+
20
+ You can create `JsonSelection` instances in multiple ways: from existing `Json` values, or using companion object constructors. Each approach is useful for different scenarios—direct navigation for existing JSON, and explicit construction for building selections programmatically.
21
+
22
+ ### From Json Values
23
+
24
+ Create a `JsonSelection` directly from a `Json` value by calling navigation methods:
25
+
26
+ ```scala
27
+ import zio.blocks.schema.json.{Json, JsonSelection}
28
+
29
+ val json = Json.parseUnsafe("""{"name": "Alice"}""")
30
+
31
+ // Get a single field
32
+ val name: JsonSelection = json.get("name")
33
+
34
+ // Get array element by index
35
+ val values = Json.parseUnsafe("[1, 2, 3]")
36
+ val selected: JsonSelection = values.get(0)
37
+ ```
38
+
39
+ ### From Companion Object
40
+
41
+ Construct `JsonSelection` instances programmatically using the companion object methods for empty, successful, and failed selections:
42
+
43
+ ```scala
44
+ import zio.blocks.schema._
45
+ import zio.blocks.schema.json.{Json, JsonSelection}
46
+
47
+ // Empty successful selection
48
+ val empty = JsonSelection.empty
49
+
50
+ // Succeed with a single value
51
+ val success = JsonSelection.succeed(Json.String("hello"))
52
+
53
+ // Succeed with multiple values
54
+ val many = JsonSelection.succeedMany(
55
+ zio.blocks.chunk.Chunk.from(Seq(Json.Number(1), Json.Number(2)))
56
+ )
57
+
58
+ // Fail with an error
59
+ val failure = JsonSelection.fail(SchemaError("not found"))
60
+ ```
61
+
62
+ ## Navigation Operations
63
+
64
+ Navigate through JSON structures using three complementary approaches: field access for object properties, array indexing for elements, and path expressions for complex nested navigation.
65
+
66
+ ### Field Navigation
67
+
68
+ Navigate to object fields using `JsonSelection#get` with a field name:
69
+
70
+ ```scala
71
+ import zio.blocks.schema.json.Json
72
+
73
+ val data = Json.parseUnsafe("""{
74
+ "user": {
75
+ "name": "Bob",
76
+ "email": "bob@example.com"
77
+ }
78
+ }""")
79
+
80
+ // Single field access
81
+ val user = data.get("user")
82
+
83
+ // Chained field access
84
+ val name = data.get("user").get("name")
85
+
86
+ // Multiple levels of nesting
87
+ val email = data.get("user").get("email")
88
+ ```
89
+
90
+ ### Array Navigation
91
+
92
+ Access array elements by index using `JsonSelection#apply` or `JsonSelection#get`:
93
+
94
+ ```scala
95
+ import zio.blocks.schema.json.Json
96
+
97
+ val data = Json.parseUnsafe("""[
98
+ {"id": 1, "name": "Alice"},
99
+ {"id": 2, "name": "Bob"}
100
+ ]""")
101
+
102
+ // Index access (0-based)
103
+ val first = data.get(0)
104
+
105
+ // Chained index and field access
106
+ val firstName = data.get(0).get("name")
107
+ val secondId = data.get(1).get("id")
108
+ ```
109
+
110
+ ### Path-Based Navigation
111
+
112
+ Use path interpolators (e.g., `p".company.employees[0].name"`) to navigate deeply nested structures in a single operation:
113
+
114
+ ```scala
115
+ import zio.blocks.schema._
116
+ import zio.blocks.schema.json.Json
117
+
118
+ val data = Json.Object(
119
+ "company" -> Json.Object(
120
+ "employees" -> Json.Array(
121
+ Json.Object("name" -> Json.String("Alice"), "department" -> Json.String("Engineering")),
122
+ Json.Object("name" -> Json.String("Bob"), "department" -> Json.String("Sales"))
123
+ )
124
+ )
125
+ )
126
+
127
+ // Navigate using path interpolator
128
+ val path = p".company.employees[0].name"
129
+ val firstEmpName = data.get(path) // JsonSelection(Right(Chunk(Json.String("Alice"))))
130
+ ```
131
+
132
+ ## Filtering and Querying
133
+
134
+ Reduce selections to only the values you need by filtering by JSON type or custom predicates. This enables working with heterogeneous JSON arrays where values may be of different types.
135
+
136
+ ### Filter by Type
137
+
138
+ Keep only values of a specific JSON type using type-filtering methods like `JsonSelection#strings`, `JsonSelection#numbers`, and `JsonSelection#booleans`:
139
+
140
+ ```scala
141
+ import zio.blocks.schema.json.{Json, JsonSelection}
142
+
143
+ val mixed = Json.parseUnsafe("""["text", 42, true, "more text"]""")
144
+
145
+ // Create a selection containing all array elements, then filter by type
146
+ val allElements = JsonSelection.succeedMany(mixed.elements)
147
+ val strings = allElements.strings // JsonSelection with string values
148
+ val numbers = allElements.numbers // JsonSelection with number values
149
+ val booleans = allElements.booleans // JsonSelection with boolean values
150
+ ```
151
+
152
+ ### Filter with Predicate
153
+
154
+ Use custom predicates with `JsonSelection#filter` to keep only values that match specific conditions:
155
+
156
+ ```scala
157
+ import zio.blocks.schema.json.{Json, JsonSelection}
158
+
159
+ val data = Json.parseUnsafe("[1, 2, 3, 4]")
160
+
161
+ // Create selection and filter with predicate
162
+ val allElements = JsonSelection.succeedMany(data.elements)
163
+ val evenOnly = allElements.filter { json =>
164
+ json match {
165
+ case Json.Number(n) => n.toInt % 2 == 0
166
+ case _ => false
167
+ }
168
+ }
169
+ ```
170
+
171
+ ## Extracting Values
172
+
173
+ Extract concrete values from selections by decoding them to Scala types, checking single vs. multiple values, or inspecting selection state without extraction.
174
+
175
+ ### Type Decoding
176
+
177
+ Decode a single selected value to a Scala type using `JsonSelection#as`, which fails if more than one value is selected:
178
+
179
+ ```scala
180
+ import zio.blocks.schema._
181
+ import zio.blocks.schema.json.Json
182
+
183
+ // Decode to Scala types
184
+ val selection = Json.parseUnsafe("""{"count": 42}""")
185
+
186
+ val count: Either[SchemaError, Int] = selection.get("count").as[Int]
187
+ val str: Either[SchemaError, String] = selection.get("count").as[String] // Left (type mismatch)
188
+ ```
189
+
190
+ ### Multiple Decoding
191
+
192
+ Decode all selected values to a collection using `JsonSelection#asAll`, which succeeds even if the selection is empty:
193
+
194
+ ```scala
195
+ import zio.blocks.schema._
196
+ import zio.blocks.schema.json.{Json, JsonSelection}
197
+
198
+ val data = Json.parseUnsafe("""["Alice", "Bob", "Charlie"]""")
199
+
200
+ // Create selection of all array elements and decode
201
+ val allElements = JsonSelection.succeedMany(data.elements)
202
+ val names: Either[SchemaError, Seq[String]] = allElements.asAll[String].map(_.toSeq)
203
+ ```
204
+
205
+ ### Extract Single Value
206
+
207
+ Use `JsonSelection#one` to extract exactly one value, failing if the selection contains zero or more than one value:
208
+
209
+ ```scala
210
+ import zio.blocks.schema._
211
+ import zio.blocks.schema.json.{Json, JsonSelection}
212
+
213
+ val arr = Json.parseUnsafe("[1, 2]")
214
+
215
+ // Get exactly one value from a selection (fails if 0 or more than 1)
216
+ val single = arr.get(0).one // Right(Json.Number(1))
217
+ val multiple = JsonSelection.succeedMany(arr.elements).one // Left(SchemaError(...))
218
+ ```
219
+
220
+ ### Check and Get
221
+
222
+ Inspect selection state without extraction using properties like `JsonSelection#values`, `JsonSelection#error`, `JsonSelection#isSuccess`, and `JsonSelection#isFailure`:
223
+
224
+ ```scala
225
+ import zio.blocks.schema.json.{Json, JsonSelection}
226
+
227
+ val data = Json.Object("x" -> Json.Number(1))
228
+
229
+ // Safe option extraction
230
+ val x: Option[Json] = data.get("x").values.flatMap(_.headOption)
231
+
232
+ // Check if selection succeeded
233
+ val success = data.get("exists").isSuccess // true if "exists" field found
234
+ val failed = data.get("notFound").isFailure // true if field not found
235
+ ```
236
+
237
+ ## Size and Existence Checks
238
+
239
+ Query selection size and emptiness using `JsonSelection#size`, `JsonSelection#isEmpty`, and `JsonSelection#nonEmpty`:
240
+
241
+ ```scala
242
+ import zio.blocks.schema.json.{Json, JsonSelection}
243
+
244
+ val data = Json.parseUnsafe("[1, 2, 3]")
245
+
246
+ // Create selection and check size
247
+ val selection = JsonSelection.succeedMany(data.elements)
248
+ val size = selection.size // 3
249
+ val isEmpty = selection.isEmpty // false
250
+ val nonEmpty = selection.nonEmpty // true
251
+ ```
252
+
253
+ ## Modifying Selections
254
+
255
+ Use `JsonSelection` to update values at specific paths using `set` for replacement or `modify` for transformation:
256
+
257
+ ```scala
258
+ import zio.blocks.schema._
259
+ import zio.blocks.schema.json.Json
260
+
261
+ val original = Json.Object("count" -> Json.Number(0))
262
+
263
+ // Set a new value
264
+ val updated = original.set(p".count", Json.Number(1))
265
+
266
+ // Modify with a function
267
+ val modified = original.modify(p".count") {
268
+ case Json.Number(n) => Json.Number(n + 1)
269
+ case other => other
270
+ }
271
+ ```
272
+
273
+ ## Error Handling
274
+
275
+ Selections propagate errors through the chain:
276
+
277
+ ```scala
278
+ import zio.blocks.schema._
279
+ import zio.blocks.schema.json.Json
280
+
281
+ val data = Json.Object("name" -> Json.String("Alice"))
282
+
283
+ // Missing field returns error
284
+ val missing = data.get("age").error // Some(SchemaError("field not found"))
285
+
286
+ // Chain continues with error
287
+ val stillMissing = data.get("age").get("nested") // Still carries the error
288
+
289
+ // Check error state
290
+ val result = data.get("x")
291
+ val maybeError: Option[SchemaError] = result.error
292
+ val maybeValues = result.values // None if error
293
+ ```
294
+
295
+ ## Integration with Codecs
296
+
297
+ `JsonSelection` integrates seamlessly with `JsonCodec` and `Schema`:
298
+
299
+ ```scala
300
+ import zio.blocks.schema._
301
+ import zio.blocks.schema.json.{Json, JsonSelection}
302
+ import zio.blocks.chunk.Chunk
303
+
304
+ case class User(name: String, email: String)
305
+ object User { implicit val schema: Schema[User] = Schema.derived }
306
+
307
+ val users = Json.parseUnsafe("""[
308
+ {"name": "Alice", "email": "alice@example.com"},
309
+ {"name": "Bob", "email": "bob@example.com"}
310
+ ]""")
311
+
312
+ // Navigate and decode in one chain
313
+ val firstUser: Either[SchemaError, User] = users.get(0).as[User]
314
+ val allUsers: Either[SchemaError, Chunk[User]] = JsonSelection.succeedMany(users.elements).asAll[User]
315
+ ```
316
+
317
+ ## Performance Notes
318
+
319
+ - **Zero-allocation navigation:** `JsonSelection` itself is a value type (AnyVal) and compiles to no allocation
320
+ - **Lazy chaining:** Operations chain without intermediate allocations; only final extraction materializes values
321
+ - **Error short-circuiting:** Failed selections don't execute further operations
322
+ - **Streaming-friendly:** For large JSON, use `JsonSelection#get` selectively rather than iterating over all values
@@ -3,7 +3,7 @@ id: json
3
3
  title: "Json"
4
4
  ---
5
5
 
6
- `Json` is an algebraic data type (ADT) for representing JSON values in ZIO Blocks. It provides a type-safe, schema-free way to work with JSON data, enabling navigation, transformation, merging, and querying without losing fidelity.
6
+ `Json` is a type-safe, schema-free representation of JSON values that enables navigation, transformation, merging, and querying without losing fidelity.
7
7
 
8
8
  ## Overview
9
9
 
@@ -212,7 +212,8 @@ result.isFailure // false
212
212
  import zio.blocks.schema.json.{Json, JsonSelection}
213
213
  import zio.blocks.schema.SchemaError
214
214
 
215
- val selection: JsonSelection = ???
215
+ val json = Json.parseUnsafe("""{"name": "Alice", "age": 30}""")
216
+ val selection: JsonSelection = json.get("name")
216
217
 
217
218
  // Get single value (exactly one required)
218
219
  val oneValue: Either[SchemaError, Json] = selection.one
@@ -557,41 +558,9 @@ Schema[java.time.ZonedDateTime].jsonCodec
557
558
  Schema[java.util.UUID].jsonCodec
558
559
  ```
559
560
 
560
- ### Encoding/Decoding of Primitives
561
-
562
- ```scala
563
- import zio.blocks.schema._
564
-
565
- // Encode Scala values to Json
566
- val intJson = 42.toJson // Json.Number(42)
567
- val strJson = "hello".toJson // Json.String("hello")
568
-
569
- // Decode Json to Scala values
570
- val intResult = intJson.as[Int] // Right(42)
571
- val strResult = strJson.as[String] // Right("hello")
572
- ```
573
-
574
- ### Encoding/Decoding of Case Classes
575
-
576
- For complex types, use Schema-based derivation:
577
-
578
- ```scala
579
- import zio.blocks.schema._
580
-
581
- case class Person(name: String, age: Int)
582
-
583
- object Person {
584
- implicit val schema: Schema[Person] = Schema.derived
585
- }
586
-
587
- val person = Person("Alice", 30)
588
- val json = person.toJson
589
- val decoded = json.as[Person]
590
- ```
591
-
592
561
  ### Extension Syntax
593
562
 
594
- When a `Schema` is in scope, you can use convenient extension methods directly on values:
563
+ When a `Schema` is in scope, you can use convenient extension methods on any Scala value to encode and decode JSON. These work on primitives, case classes, and all other types:
595
564
 
596
565
  ```scala
597
566
  import zio.blocks.schema._
@@ -617,30 +586,15 @@ val parsed = """{"name":"Bob","age":25}""".fromJson[Person] // Right(Person("Bo
617
586
 
618
587
  // Parse from bytes
619
588
  val fromBytes = jsonBytes.fromJson[Person] // Right(Person("Alice", 30))
620
- ```
621
589
 
622
- These extension methods provide a more ergonomic API compared to explicitly creating encoders/decoders.
623
-
624
- ### Using the `as` Method
625
-
626
- ```scala
627
- import zio.blocks.schema._
628
- import zio.blocks.schema.json._
629
-
630
- case class Person(name: String, age: Int)
631
- object Person {
632
- implicit val schema: Schema[Person] = Schema.derived
633
- }
634
-
635
- val json = Json.parseUnsafe("""{"name": "Alice", "age": 30}""")
636
-
637
- // Decode to a specific type
638
- val person: Either[SchemaError, Person] = json.as[Person]
639
-
640
- // Unsafe version (throws on error)
641
- val personUnsafe: Person = json.asUnsafe[Person]
590
+ // Works on primitives too
591
+ val intJson = 42.toJson // Json.Number(42)
592
+ val strJson = "hello".toJson // Json.String("hello")
593
+ val intResult = intJson.as[Int] // Right(42)
642
594
  ```
643
595
 
596
+ These extension methods provide a more ergonomic API compared to explicitly creating encoders/decoders, and work consistently across all types.
597
+
644
598
  ## Printing JSON
645
599
 
646
600
  ### Basic Printing
@@ -827,7 +781,7 @@ import zio.blocks.schema.json.{Json, JsonPatch}
827
781
  val source = Json.parseUnsafe("""{"name": "Alice", "age": 30}""")
828
782
  val target = Json.parseUnsafe("""{"name": "Alice", "age": 31, "active": true}""")
829
783
 
830
- // Compute the diff
784
+ // Create a patch describing the differences
831
785
  val patch: JsonPatch = JsonPatch.diff(source, target)
832
786
 
833
787
  // The patch describes the minimal changes:
@@ -904,11 +858,13 @@ val result = combined(Json.parseUnsafe("""{"x": 1}"""))
904
858
  `JsonPatch` can be converted to and from `DynamicPatch` for interoperability with the typed patching system:
905
859
 
906
860
  ```scala
907
- import zio.blocks.schema.json.JsonPatch
861
+ import zio.blocks.schema.json.{Json, JsonPatch}
908
862
  import zio.blocks.schema.patch.DynamicPatch
909
863
  import zio.blocks.schema.SchemaError
910
864
 
911
- val jsonPatch: JsonPatch = ???
865
+ val source = Json.parseUnsafe("""{"value": 1}""")
866
+ val target = Json.parseUnsafe("""{"value": 2}""")
867
+ val jsonPatch: JsonPatch = JsonPatch.diff(source, target)
912
868
 
913
869
  // Convert to DynamicPatch
914
870
  val dynamicPatch: DynamicPatch = jsonPatch.toDynamicPatch
@@ -951,13 +907,25 @@ val result = json.get("users")(5).get("name").as[String]
951
907
  ### Error Properties
952
908
 
953
909
  ```scala
954
- import zio.blocks.schema.SchemaError
955
- import zio.blocks.schema.DynamicOptic
910
+ import zio.blocks.schema._
911
+ import zio.blocks.schema.json._
956
912
 
957
- val error: SchemaError = ???
913
+ case class User(id: Int, name: String)
914
+ object User {
915
+ implicit val schema: Schema[User] = Schema.derived
916
+ }
917
+
918
+ val codec = User.schema.derive(JsonFormat)
919
+ val invalidJson = """{"id": "not-a-number", "name": "Alice"}"""
920
+ val result = codec.decode(invalidJson)
958
921
 
959
- error.message // Error description
960
- error.errors.head.source // DynamicOptic path to error location
922
+ // Extract error properties when decoding fails
923
+ result match {
924
+ case Left(error: SchemaError) =>
925
+ error.message // Error description
926
+ error.errors.head.source // DynamicOptic path to error location
927
+ case Right(_) => ()
928
+ }
961
929
  ```
962
930
 
963
931
  ## Cross-Platform Support