Skip to content

Commit 04a3ed6

Browse files
committed
Doc and test the other function
1 parent b42b075 commit 04a3ed6

File tree

2 files changed

+168
-1
lines changed

2 files changed

+168
-1
lines changed

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,53 @@ try {
8787
}
8888
```
8989

90+
## API Reference
91+
92+
### `convertJsonSchemaToZod(schema)`
93+
94+
Converts a JSON Schema object to a complete Zod schema.
95+
96+
- **Parameters**:
97+
- `schema` (Object): A JSON Schema object
98+
- **Returns**:
99+
- A Zod schema that validates according to the JSON Schema
100+
101+
### `jsonSchemaObjectToZodRawShape(schema)`
102+
103+
Extracts the object properties from a JSON Schema object into a Zod raw shape. This is useful when you want to combine the properties with other Zod object configurations.
104+
105+
- **Parameters**:
106+
- `schema` (Object): A JSON Schema object that should have a `properties` field
107+
- **Returns**:
108+
- A `ZodRawShape` object that can be used with `z.object()`
109+
110+
**Example**:
111+
112+
```typescript
113+
import { jsonSchemaObjectToZodRawShape } from 'zod-from-json-schema';
114+
import { z } from 'zod';
115+
116+
const jsonSchema = {
117+
properties: {
118+
name: { type: "string" },
119+
age: { type: "integer" }
120+
},
121+
required: ["name"]
122+
};
123+
124+
// Get just the property definitions
125+
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);
126+
127+
// Add custom handling
128+
const customSchema = z.object({
129+
...rawShape,
130+
// Add additional fields not in the JSON Schema
131+
createdAt: z.date().default(() => new Date())
132+
}).refine(data => data.age > 18, {
133+
message: "Age must be over 18 to continue"
134+
});
135+
```
136+
90137
## Supported JSON Schema Features
91138

92139
This library supports the following JSON Schema features:

src/index.test.ts

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, it, expect } from "vitest";
2-
import { convertJsonSchemaToZod } from "./index";
2+
import { convertJsonSchemaToZod, jsonSchemaObjectToZodRawShape } from "./index";
33
import { zodToJsonSchema } from "zod-to-json-schema";
4+
import { z } from "zod";
45

56
describe("convertJsonSchemaToZod", () => {
67
it("should correctly convert a schema with additionalProperties: true", () => {
@@ -185,4 +186,123 @@ describe("convertJsonSchemaToZod", () => {
185186
expect(resultSchema.items).toEqual({ type: "string" });
186187
});
187188
});
189+
});
190+
191+
describe("jsonSchemaObjectToZodRawShape", () => {
192+
it("should extract properties from a JSON schema", () => {
193+
const jsonSchema = {
194+
type: "object",
195+
properties: {
196+
name: { type: "string" },
197+
age: { type: "integer" },
198+
isActive: { type: "boolean" },
199+
},
200+
required: ["name", "age"]
201+
};
202+
203+
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);
204+
205+
// Properties should exist in the raw shape
206+
expect(rawShape).toHaveProperty("name");
207+
expect(rawShape).toHaveProperty("age");
208+
expect(rawShape).toHaveProperty("isActive");
209+
210+
// Verify types are correct
211+
expect(rawShape.name instanceof z.ZodString).toBe(true);
212+
expect(rawShape.age instanceof z.ZodNumber).toBe(true);
213+
expect(rawShape.isActive instanceof z.ZodBoolean).toBe(true);
214+
});
215+
216+
it("should handle empty properties", () => {
217+
const jsonSchema = {
218+
type: "object",
219+
properties: {}
220+
};
221+
222+
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);
223+
expect(Object.keys(rawShape).length).toBe(0);
224+
expect(rawShape).toEqual({});
225+
});
226+
227+
it("should handle missing properties field", () => {
228+
const jsonSchema = {
229+
type: "object"
230+
};
231+
232+
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);
233+
expect(Object.keys(rawShape).length).toBe(0);
234+
expect(rawShape).toEqual({});
235+
});
236+
237+
it("should correctly convert nested object properties", () => {
238+
const jsonSchema = {
239+
type: "object",
240+
properties: {
241+
user: {
242+
type: "object",
243+
properties: {
244+
name: { type: "string" },
245+
email: { type: "string" }
246+
},
247+
required: ["name"]
248+
}
249+
}
250+
};
251+
252+
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);
253+
254+
expect(rawShape).toHaveProperty("user");
255+
expect(rawShape.user instanceof z.ZodObject).toBe(true);
256+
257+
// Create a schema with the raw shape to test validation
258+
const schema = z.object(rawShape);
259+
260+
// Valid data should pass
261+
expect(() => schema.parse({
262+
user: { name: "John", email: "[email protected]" }
263+
})).not.toThrow();
264+
265+
// Missing required field should fail
266+
expect(() => schema.parse({
267+
user: { email: "[email protected]" }
268+
})).toThrow();
269+
});
270+
271+
it("should be usable to build custom schemas", () => {
272+
const jsonSchema = {
273+
properties: {
274+
name: { type: "string" },
275+
age: { type: "integer" }
276+
}
277+
};
278+
279+
// Get the raw shape
280+
const rawShape = jsonSchemaObjectToZodRawShape(jsonSchema);
281+
282+
// Make fields optional manually and add custom fields
283+
const customSchema = z.object({
284+
name: rawShape.name.optional(),
285+
age: rawShape.age.optional(),
286+
createdAt: z.date().default(() => new Date())
287+
}).refine(data => data.age === undefined || data.age > 18, {
288+
message: "Age must be over 18"
289+
});
290+
291+
// Test validation with the custom schema - all fields work
292+
const validData = customSchema.parse({
293+
name: "John",
294+
age: 25
295+
});
296+
expect(validData).toHaveProperty("name", "John");
297+
expect(validData).toHaveProperty("age", 25);
298+
expect(validData).toHaveProperty("createdAt");
299+
expect(validData.createdAt instanceof Date).toBe(true);
300+
301+
// Test with missing fields
302+
const dataWithMissingField = customSchema.parse({});
303+
expect(dataWithMissingField).toHaveProperty("createdAt");
304+
305+
// Test refinement with invalid age
306+
expect(() => customSchema.parse({ age: 16 })).toThrow();
307+
});
188308
});

0 commit comments

Comments
 (0)