JSON Schema for User Registration
Part of the JSON Toolkit{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8}}}the two fields nearly every registration form needs — the full version below adds username, age, and terms acceptance
Explanation
A registration form usually needs more than "is this valid JSON" — it needs "does this object have the fields I require, in the shapes I expect, and nothing extra I didn't ask for." A full schema for that looks like:
{
"type": "object",
"properties": {
"username": { "type": "string", "minLength": 3, "maxLength": 20, "pattern": "^[a-zA-Z0-9_]+$" },
"email": { "type": "string", "format": "email" },
"password": { "type": "string", "minLength": 8 },
"age": { "type": "integer", "minimum": 13 },
"acceptedTerms": { "const": true }
},
"required": ["username", "email", "password", "acceptedTerms"],
"additionalProperties": false
}required lists username, email, password, and acceptedTerms — age is defined but left out of required, so it's an optional field that's still type-checked whenever it's present. acceptedTerms uses const: true rather than type: boolean, because a form that submits "acceptedTerms": false for an unchecked box should fail validation, not just pass a type check.
additionalProperties: false is doing more than tidiness here. Without it, a client could send {"role": "admin", ...} alongside the expected fields and the schema would let it straight through — the request handler downstream might then trust a field it never meant to accept from user input. This is the classic mass assignment problem, and rejecting unknown properties at the schema level closes it before the object ever reaches your business logic.
One thing this schema deliberately can't do: verify that password matches a confirmPassword field. JSON Schema validates the shape of a single document against fixed rules — it has no keyword for "this property must equal that sibling property." Password-confirmation matching, uniqueness checks against existing accounts, and anything else that depends on comparing values to each other or to external state belongs in your application code, after the schema has already confirmed the basic shape is sound.
For the vocabulary behind keywords like required, format, and additionalProperties, see What Is JSON Schema?. For more worked examples across other shapes, see JSON Schema Examples. For the schema on the other side of this form — validating the login request afterward — see JSON Schema for Login Forms. For a schema validating a request body with an array of items rather than a flat form, see JSON Schema for API Requests.
Valid examples
{"username":"jane_doe","email":"jane@example.com","password":"correcthorsebattery","acceptedTerms":true,"age":24}Every field, including the optional age — passes every constraint.
{"username":"bob99","email":"bob@example.com","password":"hunter2222","acceptedTerms":true}age left out entirely — it's not in required, so the object is still valid without it.
{"username":"abc","email":"a@example.com","password":"12345678","acceptedTerms":true}username at exactly 3 characters and password at exactly 8 — both sit right on the minLength boundary and still pass.
Invalid examples
{"username":"jane_doe","email":"jane@example.com","acceptedTerms":true}No password field at all — fails required, which lists it as mandatory.
{"username":"jane_doe","email":"jane@example.com","password":"correcthorsebattery","acceptedTerms":false}acceptedTerms is false — it's the right type but fails const: true, which requires the box to actually be checked.
{"username":"jane_doe","email":"jane@example.com","password":"correcthorsebattery","acceptedTerms":true,"role":"admin"}An unexpected role field — additionalProperties: false rejects it outright, closing off a mass-assignment path a client shouldn't have.