<jupyter_start><jupyter_text>Structuur: JSON-schema * MongoDB/document-database: elk document (in een collection) bepaalt zijn eigen structuur* voor zoeken in een collection: (deels) gemeenschappelijke structuur van documenten nodig* met JSON-schema kun je de *structuur van een document beschrijven*; je kunt daarmee controleren of een bepaald document aan dit schema voldoet; je documenteert daarmee ook de collection* we noemen een document dat aan een JSON-schema voldoet ook wel een *instantie* (instance) van dat schema* je kunt een JSON-schema ook zien als meta-data: het is data die de structuur van andere data (documenten) beschrijft.* in MongoDB kun je een JSON-schema koppelen aan een collection, om af te dwingen dat alle documenten in die collection aan dat schema voldoen.* JSON-schema dit is niet alleen zinvol voor (document) databases, maar bijvoorbeeld ook voor:    * API's die JSON-documenten als invoer verwachten, of als resultaat opleveren;    * UI voor formulierinvoer van documenten     * (andere contexten waar JSON documenten gebruikt worden?)  Inleiding Zoals je eerder gezien hebt, bepaalt elk (JSON-)document in een MongoDB collection zijn eigen structuur: de namen en types van de velden.Voor een zoekopdracht in een collection, bijvoorbeeld naar documenten met `plaats = "Amsterdam"`, is het wel zo handig als alle documenten een veld `plaats` hebben, met een string als waarde. Een document met `{..."city": "Amsterdam"...}` komt immers niet in het zoekresultaat voor.Met een *JSON-schema* (https://json-schema.org) kun je controleren (valideren) of een JSON-document (ten minste) bepaalde velden heeft, met de juiste namen en types.Door een JSON-schema te koppelen aan een MongoDB *collection* kun je afdwingen dat alleen documenten die aan het schema voldoen aan die collection toegevoegd worden. ```{admonition} OpmerkingJe kunt een JSON-schema vergelijken met een *type* of een *class* voor JSON-documenten.Een JSON-document (instantie) is dan een waarde van dat type, of object van die class.``` We geven eerst een elementair JSON-schema voorbeeld. Voor veel programmeertalen zijn er libraries om te werken met JSON-schema. We gebruiken hier de Python-library `jsonschema`, zie https://python-jsonschema.readthedocs.io.<jupyter_code>from jsonschema import validate<jupyter_output><empty_output><jupyter_text>Dit eerste voorbeeld geeft een schema met twee velden, `naam` en `leeftijd`. Voor elk veld kun je het type aangeven. Met behulp van `required` geef je aan welke velden *verplicht* zijn.<jupyter_code>schema = {
    "type": "object",
    "properties": {
        "naam": {"type": "string"},
        "leeftijd": {"type": "integer"}
    },
    "required": ["naam"]
}<jupyter_output><empty_output><jupyter_text>Met `validate` kun je controleren of een JSON-object voldoet aan dit schema.(Alleen als dat niet het geval is krijg je een foutmelding (exception); anders niets.)<jupyter_code>object1 = {"naam": "Hans", "leeftijd": 33}
validate(instance=object1, schema=schema)<jupyter_output><empty_output><jupyter_text>In het volgende voorbeeld klopt de waarde van het veld `leeftijd` niet met het type zoals gegeven in het schema. Dit resulteert in een foutmelding.<jupyter_code>object2 = {"naam": "Kees", "leeftijd": "dertig"}
validate(instance=object2, schema=schema)<jupyter_output><empty_output><jupyter_text>Bij de volgende instantie ontbreekt het verplichte veld "naam", waarschijnlijk door de verwarring met "voornaam":<jupyter_code>object3 = {"voornaam": "Marie", "leeftijd": 21}
validate(instance=object3, schema=schema)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08620689655172414, 'fraction_numerical': 0.0027808676307007787, 'mean_word_length': 5.624309392265193, 'pattern_counts': {'":': 15, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '242027', 'license': 'MIT', 'n_tokens_mistral': 1136, 'n_tokens_neox': 1147, 'n_words': 433, 'path': 'structuur-0.ipynb', 'repo_name': 'eelcodijkstra/nosqlbook', 'size': '3596'}