Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JSON Schema For Validating API Requests

JSON Schema For Validating API Requests

When Stuart needed to build an API-first app for a client, he wanted to find a better way to do input validation. He'd just come off a quality audit role on a large-scale project where he'd seen first-hand how it just isn't feasible to expect anyone to achieve 100% input validation through entirely manual means.

That experience, and that search, led him to JSON Schema.

In this talk, Stuart will introduce you to JSON Schema. He'll show you the essential points of writing a schema, and how to use it both from PHP and from JavaScript. Finally, he'll discuss the current state of the JSON schema draft, and share the compatibility issues he's seen over the last couple of years.

Stuart Herbert

July 02, 2018

More Decks by Stuart Herbert

Other Decks in Programming


  1. Industry veteran: architect, engineer, leader, manager, mentor F/OSS contributor since

    1994 Talking and writing about PHP since 2004 Chief Software Archaeologist Building Quality @GanbaroDigital About Stuart
  2. @GanbaroDigital HTTP API Request HTTP Headers (Metadata) Request Body (Payload)

    Query Path (Route) Query Params (Filters) HTTP Verb (Method)
  3. @GanbaroDigital HTTP API Request HTTP Headers (Metadata) Request Body (Payload)

    Query Path (Route) Query Params (Filters) HTTP Verb (Method)
  4. @GanbaroDigital “ Request bodies are user input. They must be

    validated before they can be safely used.
  5. @GanbaroDigital Action Validate Format Filter Input Validate Format Escape Output

    JSON Schema JSON Schema View / Template JSON Schema API Request API Response Model / Controller
  6. @GanbaroDigital “ If your API accepts JSON payloads JSON schema

    can be part of your input validation process.
  7. @GanbaroDigital “ If your API returns JSON payloads JSON schema

    can be part of your quality assurance process.
  8. @GanbaroDigital “ If your API client 
 sends or receives

    JSON payloads JSON schema can be part of your robustness process.
  9. @GanbaroDigital * 'integer' is a special form of 'number' because

    Javascript doesn't support separate integer and float types
  10. @GanbaroDigital “ In the spec, they're called "validation keywords". It's

    easier to design a JSON schema if you think of them as 'constraints'.
  11. @GanbaroDigital Incoming Data Is Only Rejected If ... 1. You

    define a constraint 2. ... that the incoming data falls foul of
  12. @GanbaroDigital The query path is a namespace. Use it to

    leave space for the undiscovered country.
  13. @GanbaroDigital { "uid": "one thousand and one", "username": "stuart", "password":

    "totally-insecure", "groups": [ 1, 1001 ], "description": "Stuart Herbert" }
  14. @GanbaroDigital { "uid": "one thousand and one", "username": "stuart", "password":

    "totally-insecure", "groups": [ 1, 1001 ], "description": "Stuart Herbert" } Reject
  15. @GanbaroDigital We haven't defined a constraint to reject negative values.

    So, they pass validation. Even though they're invalid.
  16. @GanbaroDigital We've defined constraints for a UNIX user ID. Wouldn't

    it be great if we could split that out, for future reuse?
  17. @GanbaroDigital A compound JSON Schema is a single JSON file

    that describes multiple data structures.
  18. @GanbaroDigital $id in our subschema defines a URI #fragment This

    gets concatenated to the $id at the top of the file.
  19. @GanbaroDigital Other approaches to subschema IDs are available. This one

    works everywhere, and doesn't break people's brains.
  20. @GanbaroDigital { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://ganbarodigital.com/schemas/unix", "definitions": { "uid": {

    "$id": "#uid", "type": "integer", "minimum": 1, "maximum": 4294967294 }, "user-record": { "$id": "#user-record", "type": "object", "properties": { "uid": { "$ref": "#uid" } } } } }
  21. @GanbaroDigital { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://ganbarodigital.com/schemas/unix", "definitions": { "uid": {

    "$id": "#uid", "type": "integer", "minimum": 1, "maximum": 4294967294 }, "user-record": { "$id": "#user-record", "type": "object", "properties": { "uid": { "$ref": "#uid" } } } } }
  22. @GanbaroDigital Watch out for packages that go beyond the spec.

    You can't use those schemas anywhere else.
  23. @GanbaroDigital My gut feel is that it's going to take

    several more drafts before they nail it.
  24. @GanbaroDigital • PHP implementations use industry-standard PCRE regular expressions •

    Javascript implementations all use ECMA-262? • What do Java / .NET / etc etc use?
  25. @GanbaroDigital { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://ganbarodigital.com/schemas/unix", "definitions": { "gid": {

    "$id": "#gid", "$ref": "#uid" }, "groups": { "$id": "#groups", "type": "array", "items": { "$ref": "#gid" }, "additionalItems": false, "minItems": 1 } } }
  26. @GanbaroDigital { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://ganbarodigital.com/schemas/unix", "definitions": { "gid": {

    "$id": "#gid", "$ref": "#uid" }, "groups": { "$id": "#groups", "type": "array", "items": { "$ref": "#gid" }, "additionalItems": false, "minItems": 1 } } }
  27. @GanbaroDigital That schema only ensures that "groups" is an array

    and each entry in that array is formatted as a group ID.
  28. @GanbaroDigital It does not, and cannot ensure that each group

    ID: actually exists ... is suitable for the user ... ... or any other validation that belongs in your business logic.
  29. @GanbaroDigital “ If it's hard to write a JSON Schema

    for, it'll be hard for an API user to deal with too.
  30. @GanbaroDigital Use application/vnd+<schema> as API content types. Then you can

    delegate JSON Schema validation to a middleware component.