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

Validating JSON with JSON Schema

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

Validating JSON with JSON Schema

My talk from Berlin PHP Usergroup, December 2013, about the benefits of using JSON schema for validating complex JSON data

Avatar for Anne-Julia Seitz

Anne-Julia Seitz

December 03, 2013

More Decks by Anne-Julia Seitz

Other Decks in Technology

Transcript

  1. About me → Anne-Julia Scheuermann → Creating Web-Applications since 2004

    → Developing information literacy solutions for
  2. Custom validation protected function isValidUnformatted(array $data) { if (empty($data['data'])) {

    return false; // no data sent } $data = $data['data']; $source = $data['source']; $style = empty($data['style']) ? null : $data['style']; $structure = $this->getStructure($source, $style); $allowedTopLevelFields = $this->getOtherValidFields(); $ignoredDataFields = $this->getIgnoredFields(); // source if (!empty($structure['source_data'])) { if (empty($data[$source])) { $this->errors[] = 'needed source data missing'; return false; } $notAllowed = array_diff_key($data[$source], array_flip($structure['source_data'])); // +300 lines of code more
  3. PHPMD warnings /!\ /** * @param array $data * *

    @Todo Fix suppressed warnings * @SuppressWarnings( * PHPMD.CyclomaticComplexity, * PHPMD.NPathComplexity * ) * @return bool */ protected function isValidUnformatted(array $data) { //...
  4. DTD for SGML <!DOCTYPE HTML PUBLIC ”-//W3C//DTD HTML 4.01//EN” ”http://www.w3.org/TR/html4/strict.dtd”>

    <!--=================== Generic Attributes ===============================--> <!ENTITY % coreattrs ”id ID #IMPLIED -- document-wide unique id -- class CDATA #IMPLIED -- space-separated list of classes -- style %StyleSheet; #IMPLIED -- associated style info -- title %Text; #IMPLIED -- advisory title --” >
  5. XSD for XML (XHTML) <?xml version=”1.0”?> <xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”> <xs:element name=”note”>

    <xs:complexType> <xs:sequence> <xs:element name=”to” type=”xs:string”/> <xs:element name=”from” type=”xs:string”/> <xs:element name=”body” type=”xs:string”/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
  6. number range 10 11 40 { ”type”: ”number”, “minimum”: 10,

    “maximum”: 40, “exclusiveMinimum”: true, “exclusiveMaximum”: false }
  7. array [1, 2, 3, 4, 5] [1, “2”, {“3”:”4 and

    5”}, [42]] {”type”: ”array”} {“this”: “is an object”}
  8. array items [] [1, 2, 3, 4, 5] [1, 2,

    3, 4, “5”] { ”type”: ”array”, “items”: {“type”: “number”} }
  9. {”author”: ”A. A. Milne”, ”year”: 1882} properties { ”type”: ”object”,

    ”properties”: { ”author”: {”type”: ”string”}, ”year”: {”type”: ”number”} } } {”year”: ”1882”} {”author”: ”A. A. Milne”} {}
  10. {”author”: ”A. A Milne”, ”title”: 1882} required properties { ”type”:

    ”object”, ”properties”: { ”author”: {”type”: ”string”}, ”title”: {”type”: ”string”}}, ”required”: [”title”] } {} {”author”: ”A. A Milne”, ”title”: ”Winni the Pooh”, ”year”: 1926} {”author”: “A. A Milne”}
  11. additional properties { ”type”: ”object”, ”properties”: { ”author”: {”type”: ”string”},

    ”title”: {”type”: ”string”} }, ”additionalProperties”: false } {”title”: []} {} {”author”: ”A. A. Milne”, ”title”: ”Winni the Pooh”, ”year”: 1926} {”author”: ”A. A. Milne”, ”title”: ”Winni the Pooh”}
  12. {”a”: ”aa”, “b”: “bb”} number of properties { ”type”: ”object”,

    ”minProperties”: 1, ”maxProperties”: 2 } {} {”a”: ”aa”} {”a”: ”aa”, “b”: “bb”, “c”: “cc”}
  13. {”name”: ”Alan”, “birthday”: “1882-01-18”} property dependencies { ”type”: ”object”, ”properties”:

    {“name”: {“type”: “string”}, “birthday”: {“type”: “string”}}, ”dependencies”: { “birthday”: [“name”]} } {”name”: ”Alan”} {“birthday”: “1882-01-18”}
  14. {”name”: ”Alan”, “birthday”: “1882-01-18”} schema dependencies { ”type”: ”object”, ”properties”:

    { “birthday”: {“type”: “string”}}, ”dependencies”: { “birthday”: { “properties”: {“name”: {“type”: “string”}}}} } {”name”: ”Alan”} {“birthday”: “1882-01-18”}
  15. {”PHPUnit”: ”testing”, “PHPCS”: “styling”} pattern properties { ”type”: ”object”, ”patternProperties”:

    { “^PHP”: {“type”: “string”}}, “additionalProperties”: {“type”: “integer”} } {”BeHat”: ”accepting”} {“PHPLOC”: 9001} {“LOC”: 9001}
  16. “one” “eleven” 1 -11 Combining with oneOf, anyOf, allOf {

    ”anyOf”: [ {“type”: “string”, “maxLength”: 5}, {“type”: “number”, “minimum”: 0} ] }
  17. title, description & default { ”title”: ”Expressive title”, ”description”: “Take

    time to explain”, ”default”: “Validators ignore this keyword” }
  18. definitions { “$schema”: “http://json-schema.org/draft-04/schema#”, “definitions”: { "address": { "type": "object",

    "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"] } } }
  19. $ref & definitions { “$schema”: “http://json-schema.org/draft-04/schema#”, “definitions”: { "address": {

    "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"] } } "type": "object", "properties": { "billing_address": { "$ref": "#/definitions/address" }, "shipping_address": { "$ref": "#/definitions/address" } } }
  20. $ref & definitions { “$schema”: “http://json-schema.org/draft-04/schema#”, “description”: “This schema defines

    an address”, "type": "object", "properties": { "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"] } { “$schema”: “http://json-schema.org/draft-04/schema#”, “description”: “This schema describes an order”, "type": "object", "properties": { "billing_address": { "$ref": "address.json#" }, "shipping_address": { "$ref": "address.json#" } } } address.json order.json
  21. Validation Libraries geraintluff/jsv4-php 11 commits, 1 contributor hasbridge/php-json-schema 28 commits,

    2 contributors, not yet feature complete justinrainbow/json-schema 202 commits, 21 contributors
  22. Preparing validation with json-schema // Get the schema as object

    $retriever = new JsonSchema\Uri\UriRetriever; $schema = $retriever->retrieve('file://' . realpath('schema.json')); // Resolve references $refResolver = new JsonSchema\RefResolver($retriever); $refResolver->resolve($schema, 'file://' . __DIR__);
  23. Validation with json-schema /** * Validate json against schema *

    * @param string $data * @param string $schema * * @return bool */ public function isValid($data, $schema) { $data = json_decode($data); $this->validator->check($data, $schema); $this->errors = $this->validator->getErrors(); return $this->validator->isValid(); }
  24. Less code /** * Validate json against schema * *

    @param string $data * @param string $schema * * @return bool */ public function isValid($data, $schema) { $data = json_decode($data); $this->validator->check($data, $schema); $this->errors = $this->validator->getErrors(); return $this->validator->isValid(); }