# Model validation and serialization
Source: https://speakeasy.com/docs/sdks/customize/typescript/model-validation-and-serialization

Speakeasy TypeScript SDKs support model validation and serialization backed by Zod. This feature enables validation of data against models and easy serialization or deserialization of data to and from JSON.

## Example

As an example, consider the following model definition:

```typescript filename="<sdk-root>/src/models/components/book.ts"
import * as z from "zod";

export type Book = {
  /**
   * The unique identifier for the book
   */
  id: string;
  /**
   * The title of the book
   */
  title: string;
  /**
   * The author of the book
   */
  author: string;
};
```

### From JSON

```typescript filename="example.ts"
import { bookFromJSON, bookToJSON } from "my-sdk/models/components/book";

const result = bookFromJSON('{"id":"1","title":"1984","author":"George Orwell"}');
if (result.ok) {
  console.log(result.value);
  //                 👆 result.value is of type `Book`
} else {
  // Handle validation errors
  console.error(result.error);
}
```

### To JSON

```typescript filename="example.ts"
const jsonString = bookToJSON({ id: "1", title: "1984", author: "George Orwell" });
// jsonString is of type `string`
```

## Forward compatibility and fault tolerance

Speakeasy TypeScript SDKs are designed to handle API evolution gracefully. The deserialization layer includes several features that make SDKs more resilient to changes in API responses.

### Forward-compatible enums

Enums in responses automatically accept unknown values, so new enum values added by the API won't break existing SDK users. Unknown values are captured in a type-safe `Unrecognized<string>` wrapper. Configure this behavior with `forwardCompatibleEnumsByDefault` in your `gen.yaml`, or control individual enums with `x-speakeasy-unknown-values: allow` or `x-speakeasy-unknown-values: disallow` in your OpenAPI spec.

### Forward-compatible unions

Discriminated unions accept unknown discriminator values, capturing them with their raw data accessible via the `UNKNOWN` discriminator value. Configure this with `forwardCompatibleUnionsByDefault: tagged-only` in your `gen.yaml`.

### Lax mode

When `laxMode: lax` is enabled (the default), the SDK gracefully handles missing or mistyped fields by filling in sensible zero-value defaults rather than failing deserialization. This ensures SDKs continue working even when API responses don't perfectly match the expected schema, while maintaining type safety.

### Smart union deserialization

The `unionStrategy: populated-fields` setting (enabled by default) picks the union option with the most matching fields, making deserialization more robust when union types aren't well-discriminated.

For more details, see the [forward compatibility documentation](/docs/sdks/manage/forward-compatibility) and the [TypeScript configuration reference](/docs/speakeasy-reference/generation/ts-config).