You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`CodecMapper` is a schema-first serialization library for F# focused on explicit wire contracts, symmetric encode/decode behavior, and execution that stays friendly to Native AOT and Fable-style targets.
17
+
`CodecMapper` is a schema-first serialization library for F# focused on explicit wire contracts, symmetric encode/decode behavior, and portability to Native AOT and Fable-style targets.
18
18
19
-
It is for the cases where serializer attributes and implicit conventions stop being helpful: you want the wire shape to be visible in code, you want encode and decode to stay in sync, and you want the contract to read like the data it describes.
20
-
21
-
The core idea is simple: define one schema that mirrors your record shape, then compile it into reusable codecs.
22
-
23
-
That sits between two common extremes:
24
-
25
-
- Put serializer attributes directly on domain types and let wire concerns leak into the model.
26
-
- Introduce separate DTOs and mapping layers so the wire contract stays explicit, but now maintain extra types and conversion code.
27
-
28
-
`CodecMapper` keeps the useful part of the DTO approach, explicit contracts, without forcing a duplicate object model for every message shape. The schema is the contract, and it sits next to the data instead of behind a second translation layer.
19
+
It is for cases where serializer attributes and implicit conventions stop being helpful. You define one schema that mirrors the wire shape, then compile it into reusable codecs.
29
20
30
21
## Why the schema feels different
31
22
@@ -84,16 +75,13 @@ The result is not hidden serializer behavior. It is the contract itself, written
84
75
85
76
If you want the compile step to read a bit smaller in samples, the format modules also expose `Json.codec`, `Xml.codec`, `Yaml.codec`, and `KeyValue.codec` as direct aliases for `compile`.
86
77
87
-
## Why this is useful
78
+
## Why use it
88
79
89
80
- The schema mirrors the data, so changes to the wire contract are visible in one place.
90
81
- Encode and decode come from the same definition, so drift is harder to introduce accidentally.
91
82
-`Json.compile` / `Json.codec` and `Xml.compile` / `Xml.codec` reuse the same schema instead of making you maintain separate mappings.
92
83
- Domain refinement stays explicit through `Schema.map` and `Schema.tryMap` instead of being buried in serializer settings.
93
-
- Versioned message and config contracts stay deliberate because the wire shape is authored directly instead of inferred from whatever the current model happens to look like.
94
-
- Migration is easier to stage: keep the external contract stable, refine the in-memory domain behind `map` / `tryMap`, and only introduce DTOs when you genuinely need a separate transport model.
95
-
96
-
See [When models evolve](#when-models-evolve) for the concrete version of this tradeoff.
84
+
- Versioned message and config contracts stay deliberate because the wire shape is authored directly.
97
85
98
86
## Why not just use X?
99
87
@@ -109,35 +97,15 @@ See [When models evolve](#when-models-evolve) for the concrete version of this t
109
97
| JSON Schema-first | Varies | Varies | External schema owned | Integrating with schema-owned systems |
- Format symmetry: `CodecMapper` is centered on one contract driving both JSON and XML, while most alternatives are JSON-only or serializer-specific.
115
-
- Model evolution: `CodecMapper` keeps contract edits explicit and supports domain refinement with `Schema.map` / `Schema.tryMap` before you reach for DTO duplication. See [When models evolve](#when-models-evolve).
116
-
- Tooling relationship: `CodecMapper` can export JSON Schema from the authored contract and also import external JSON Schema when you are adapting to another system.
117
-
118
-
If your question is "why not just use `System.Text.Json`?", the short answer is: use it when convention-based object serialization is enough. Use `CodecMapper` when you want the contract itself to be visible, reviewable, reusable, and stable across model evolution.
100
+
Use `System.Text.Json` when convention-based object serialization is enough. Use `CodecMapper` when you want the contract itself to be visible, reviewable, reusable, and stable across model evolution.
119
101
120
102
## Where it fits well
121
103
122
104
`CodecMapper` is strongest when the wire contract matters and you want it to stay explicit.
123
105
124
-
For message contracts:
125
-
126
-
- Define the exact payload shape once.
127
-
- Compile it into reusable codecs.
128
-
- Keep version changes visible in the schema instead of relying on serializer conventions.
129
-
130
-
For configuration contracts:
131
-
132
-
- Treat config as a real contract rather than as incidental object serialization.
133
-
- Keep migration and versioning logic deliberate.
134
-
- Use the schema as the stable boundary even if the in-memory domain gets richer over time.
135
-
136
-
For domain models:
137
-
138
-
- Keep the domain type close to the wire contract when that is useful.
139
-
- Use `Schema.map` and `Schema.tryMap` when the runtime model should be stronger than the serialized shape.
140
-
- Introduce separate DTOs only when the transport model genuinely needs to diverge.
106
+
- Message contracts: define the payload shape once and keep changes visible in the schema.
107
+
- Config contracts: treat configuration as a versioned boundary instead of incidental object serialization.
108
+
- Domain refinement: use `Schema.map` and `Schema.tryMap` when the runtime model should be stronger than the serialized shape.
141
109
142
110
## How JSON Schema fits in
143
111
@@ -252,31 +220,14 @@ Compared with DTO-heavy designs, the difference is:
252
220
- The shared sentinel now includes selected invalid and out-of-range numeric cases, so the portability story covers failure behavior as well as happy-path round-trips.
253
221
- The contract bridge in [src/CodecMapper.Bridge](/home/adam/projects/CodecMapper/src/CodecMapper.Bridge) is `.NET`-only by design; the portable surface is the core schema/JSON/XML library in [src/CodecMapper](/home/adam/projects/CodecMapper/src/CodecMapper).
254
222
255
-
## Start here
256
-
257
-
- Read [Getting started](docs/GETTING_STARTED.md) for the core mental model and schema DSL.
258
-
259
-
## More docs
260
-
261
-
Tutorials:
262
-
263
-
-[Getting started](docs/GETTING_STARTED.md)
264
-
265
-
How-to guides:
266
-
267
-
-[How to export JSON Schema](docs/HOW_TO_EXPORT_JSON_SCHEMA.md)
268
-
-[How to import existing C# contracts](docs/HOW_TO_IMPORT_CSHARP_CONTRACTS.md)
- Start with [Getting started](docs/GETTING_STARTED.md).
226
+
- Copy from [How to model common contract patterns](docs/HOW_TO_MODEL_COMMON_CONTRACT_PATTERNS.md).
227
+
- Use [Configuration contracts guide](docs/CONFIG_CONTRACTS.md) for versioned config shapes.
228
+
- Use [How to export JSON Schema](docs/HOW_TO_EXPORT_JSON_SCHEMA.md) and [JSON Schema support reference](docs/JSON_SCHEMA_SUPPORT.md) for schema interchange.
229
+
- Use [How to import existing C# contracts](docs/HOW_TO_IMPORT_CSHARP_CONTRACTS.md) and [C# attribute bridge design](docs/CSHARP_ATTRIBUTE_BRIDGE.md) for the bridge/facade story.
230
+
- Browse the [API docs](https://adz.github.io/CodecMapper/).
-[x]**Task 32:** Added path-aware decode diagnostics across `Json`, `Xml`, `KeyValue`, and `Yaml`, including missing-field paths, collection indices/items, and `Schema.tryMap` validation context, with matching regression coverage in the unit test suite.
27
27
28
-
-[ ]**Task 33: Ship canonical pattern docs**
29
-
- Add copy-pasteable reference patterns for basic records, nested records, validated wrappers, versioned contracts, config contracts, JSON Schema import, and the C# bridge.
30
-
- Keep the examples aligned with the stable `Schema.define |> Schema.construct |> ... |> Schema.build` DSL.
31
-
- Make the “small explicit DSL” and compile-once workflow easy to discover from README and docs landing pages.
28
+
-[x]**Task 33:** Added a canonical contract-pattern guide covering basic records, nested records, validated wrappers, versioned contracts, config contracts, JSON Schema import, and the C# bridge, and linked it from the README and docs landing pages so the copy-paste patterns are easy to find.
For bridge import details and tradeoffs, see [How To Import Existing C# Contracts](HOW_TO_IMPORT_CSHARP_CONTRACTS.md) and [C# Attribute Bridge Design](CSHARP_ATTRIBUTE_BRIDGE.md).
0 commit comments