Technical Artifacts

JSON Schemas

Using JSON Schema to validate ZineCore2 records

JSON Schema provides machine-readable validation rules for ZineCore2 records. Each of the four profiles has its own JSON Schema file that defines field types, required fields, and validation constraints.

Available Schemas

All schemas use JSON Schema Draft 2020-12:

Quick Validation

Use the online Schema Validator to validate your JSON records without installing anything.

Using JSON Schema

With AJV (JavaScript/TypeScript)

npm install ajv ajv-formats
import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);

// Load schema
const schemaResponse = await fetch('https://zinecore.org/v2/schema/zinecore2.schema.json');
const schema = await schemaResponse.json();

// Compile validator
const validate = ajv.compile(schema);

// Validate a record
const record = {
  "title": "Riot Grrrl Zine",
  "creator": ["Kathleen Hanna"],
  "date": "1991",
  "subject": ["feminism", "punk-culture"],
  "format": "print"
};

const valid = validate(record);
if (!valid) {
  console.error('Validation errors:', validate.errors);
} else {
  console.log('Valid ZineCore2 record!');
}

With jsonschema (Python)

pip install jsonschema requests
import json
import requests
from jsonschema import validate, ValidationError

# Load schema
schema_url = "https://zinecore.org/v2/schema/zinecore2.schema.json"
schema = requests.get(schema_url).json()

# Your record
record = {
    "title": "Riot Grrrl Zine",
    "creator": ["Kathleen Hanna"],
    "date": "1991",
    "subject": ["feminism", "punk-culture"],
    "format": "print"
}

# Validate
try:
    validate(instance=record, schema=schema)
    print("Valid ZineCore2 record!")
except ValidationError as e:
    print(f"Validation error: {e.message}")

With jq (Command Line)

Install jq and use with validation tools:

# Download schema
curl -O https://zinecore.org/v2/schema/zinecore2.schema.json

# Check if a JSON file is well-formed
jq empty your-record.json

# Pretty-print for manual review
jq . your-record.json

For actual JSON Schema validation from command line, use ajv-cli:

npm install -g ajv-cli
ajv validate -s zinecore2.schema.json -d your-record.json

Common Validation Errors

Missing Required Fields

Error: must have required property 'title'

Solution: Every ZineCore2 record must have title, creator, subject, and format fields.

{
  "title": "Required",
  "creator": ["Required - at least one"],
  "subject": ["Required - at least one"],
  "format": "Required (print or digital)"
}

Incorrect Data Types

Error: must be array

Solution: Fields like creator, subject, series_title must be arrays, even with one value.

// ❌ Wrong
{
  "creator": "Jane Doe"
}

// ✅ Correct
{
  "creator": ["Jane Doe"]
}

Invalid Vocabulary Terms

Error: must be equal to one of the allowed values

Solution: Use valid vocabulary codes for subject, genre, agent_role, and rights fields.

// ❌ Wrong
{
  "subject": ["Feminism"]  // Wrong: capitalized, not a code
}

// ✅ Correct
{
  "subject": ["feminism"]  // Correct: vocabulary code
}

See the Vocabularies section for all valid terms.

Additional Properties

Error: must NOT have additional properties

Solution: Only use fields defined in the schema. Remove or rename custom fields.

If you need custom fields, consider:

  1. Using public_notes for free-text information
  2. Using relation to link to external records
  3. Forking the schema and maintaining your own profile extension

Schema Composition

Validating Multiple Profiles

When working with related records, validate each profile separately:

const schemas = {
  zine: await fetch('https://zinecore.org/v2/schema/zinecore2.schema.json').then(r => r.json()),
  agent: await fetch('https://zinecore.org/v2/schema/agentcore2.schema.json').then(r => r.json()),
  holding: await fetch('https://zinecore.org/v2/schema/holdingcore2.schema.json').then(r => r.json()),
  repo: await fetch('https://zinecore.org/v2/schema/repocore2.schema.json').then(r => r.json())
};

// Validate each record type
const zineValid = ajv.compile(schemas.zine)(zineRecord);
const agentValid = ajv.compile(schemas.agent)(agentRecord);
const holdingValid = ajv.compile(schemas.holding)(holdingRecord);
const repoValid = ajv.compile(schemas.repo)(repoRecord);

Referential Integrity

JSON Schema validates structure and data types, but not referential integrity (e.g., whether a creator ID actually exists in AgentCore2).

For referential integrity, use the Reference Implementation API which enforces foreign key constraints at the database level.

Form Generation

JSON Schema can generate forms automatically:

With React JSON Schema Form

npm install @rjsf/core @rjsf/utils @rjsf/validator-ajv8
import Form from "@rjsf/core";
import validator from "@rjsf/validator-ajv8";

function ZineForm() {
  const schema = {
    /* ZineCore2 schema here */
  };

  return (
    <Form
      schema={schema}
      validator={validator}
      onSubmit={({ formData }) => console.log("Submitted:", formData)}
    />
  );
}

With JSON Forms

JSON Forms provides another option for generating forms from JSON Schema with custom UI controls.

Schema Extensions

To extend a ZineCore2 schema with custom fields:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.org/my-extended-zinecore2.schema.json",
  "allOf": [
    {
      "$ref": "https://zinecore.org/v2/schema/zinecore2.schema.json"
    },
    {
      "properties": {
        "local_call_number": {
          "type": "string",
          "description": "Local classification number"
        },
        "acquisition_date": {
          "type": "string",
          "format": "date"
        }
      }
    }
  ]
}
Extended schemas are not officially part of ZineCore2 and won't validate against the canonical schemas. They're useful for internal systems but won't interoperate with other ZineCore2 implementations.

Next Steps

Copyright ©2026 ZineCore2 Contributors,