Knows supports custom graph schemas via JSON files, allowing you to define your own node and edge types with custom properties. GQL-inspired schema format (ISO/IEC 39075).
A JSON Schema is provided for validation and IDE autocompletion. To enable it, add "$schema" to your
schema file:
{
"$schema": "https://raw.githubusercontent.com/lszeremeta/knows/main/knows/schema.json",
"nodeLabel": "MyNode",
...
}IDE Validation (recommended)
Most modern IDEs validate JSON Schema automatically when $schema is present:
- VS Code: Built-in support, shows errors inline
- JetBrains IDEs: Built-in support (PyCharm, IntelliJ, WebStorm)
- Sublime Text: Use LSP or SublimeLinter-json plugin
Online Validators
- JSON Schema Validator - Paste schema and data, get instant results
- JSON Schema Lint - Real-time validation with detailed error messages
- Hyperjump JSON Schema Validator - Supports Draft 2020-12
Command Line
Using check-jsonschema (Python):
pip install check-jsonschema
check-jsonschema --schemafile schema.json my_schema.jsonUsing ajv-cli (Node.js):
npm install -g ajv-cli
ajv validate -s schema.json -d my_schema.jsonPython
import json
from jsonschema import validate, ValidationError
with open('schema.json') as f:
json_schema = json.load(f)
with open('my_schema.json') as f:
my_schema = json.load(f)
try:
validate(instance=my_schema, schema=json_schema)
print("Schema is valid!")
except ValidationError as e:
print(f"Validation error: {e.message}")Create a schema file (e.g., my_schema.json):
{
"nodeLabel": "Product",
"edgeLabel": "relatedTo",
"nodeProperties": {
"name": "String",
"price": {"type": "Float", "min": 0.99, "max": 999.99},
"category": {"enum": ["Electronics", "Clothing", "Food"]}
},
"edgeProperties": {
"similarity": {"type": "Float", "min": 0.0, "max": 1.0}
}
}Then generate a graph:
knows -n 20 -e 30 --schema my_schema.jsonA schema file is a JSON object with the following optional fields:
| Field | Type | Default | Description |
|---|---|---|---|
nodeLabel |
string | "Node" |
Label for all generated nodes |
edgeLabel |
string | "edge" |
Label for all generated edges |
nodeProperties |
object | {} |
Property definitions for nodes |
edgeProperties |
object | {} |
Property definitions for edges (supports symmetric) |
computedNodeProperties |
object | {} |
Properties computed from graph structure |
Properties can be defined in two ways:
{
"nodeProperties": {
"name": "String",
"age": "Int",
"active": "Boolean"
}
}{
"nodeProperties": {
"salary": {"type": "Int", "min": 30000, "max": 200000},
"rating": {"type": "Float", "min": 0.0, "max": 5.0, "precision": 1},
"status": {"enum": ["active", "inactive", "pending"]}
}
}| Type | Description | Example Output |
|---|---|---|
String |
Random word | "lorem" |
Name |
Full name | "John Smith" |
FirstName |
First name | "John" |
LastName |
Last name | "Smith" |
FullName |
Full name (alias for Name) | "Jane Doe" |
Email |
Email address | "john@example.com" |
Phone |
Phone number | "+1-555-123-4567" |
Address |
Full address | "123 Main St, City" |
City |
City name | "New York" |
Country |
Country name | "United States" |
Company |
Company name | "Acme Inc" |
Job |
Job title | "Software Engineer" |
Text |
Paragraph of text | Long text (configurable via maxLength) |
Sentence |
Single sentence | "Lorem ipsum dolor sit." |
Paragraph |
Full paragraph | Multiple sentences |
Url |
URL | "https://example.com" |
Color |
Color name | "blue" |
Uuid |
UUID string | "550e8400-e29b-41d4-a716-446655440000" |
| Type | Description | Constraints |
|---|---|---|
Int / Integer |
Integer number | min, max (default: 0-10000) |
Float |
Floating-point number | min, max, precision (default: 0.0-1000.0, precision 2) |
Double |
Double-precision float | min, max, precision (default: 0.0-1000.0, precision 4) |
Boolean / Bool |
Boolean value | - |
| Type | Description | Constraints |
|---|---|---|
Date |
ISO date string | min, max (default: 1970-01-01 to 2025-12-31) |
DateTime |
ISO datetime string | min, max (default: -30 years to now) |
Time |
Time string | - |
Year |
Year number | min, max (default: 1950-2025) |
Duration |
ISO 8601 duration string | min, max (default: PT0S to P1Y) |
Define a fixed set of possible values:
{
"status": {"enum": ["pending", "approved", "rejected"]}
}min: Minimum value (inclusive)max: Maximum value (inclusive)precision: Decimal places (forFloatandDouble)
{
"price": {"type": "Float", "min": 0.01, "max": 9999.99, "precision": 2}
}min: Start date in ISO format (YYYY-MM-DD)max: End date in ISO format (YYYY-MM-DD)
{
"foundedDate": {"type": "Date", "min": "1900-01-01", "max": "2025-12-31"}
}Durations use the ISO 8601 duration
format - the same notation Cypher's duration() accepts. A duration string
starts with P ("period"); a T separates the date part (years/months/weeks/days)
from the time part (hours/minutes/seconds):
| Component | Meaning | Example |
|---|---|---|
nY |
years | P2Y = 2 years |
nM (before T) |
months | P3M = 3 months |
nW |
weeks | P2W = 2 weeks |
nD |
days | P10D = 10 days |
nH (after T) |
hours | PT5H = 5 hours |
nM (after T) |
minutes | PT30M = 30 minutes |
nS (after T) |
seconds | PT45S = 45 seconds |
Components combine in order, e.g. P1Y2M10DT2H30M ("1 year, 2 months, 10 days,
2 hours, 30 minutes"). Generated values are ISO 8601 strings like P5DT3H20M;
zero components are omitted and an empty duration is rendered as PT0S.
Constraints:
min: Minimum duration as an ISO 8601 duration string (default:PT0S)max: Maximum duration as an ISO 8601 duration string (default:P1Y)
Examples:
{
"uptime": "Duration",
"warranty": {"type": "Duration", "min": "PT0S", "max": "P2Y"},
"taskTime": {"type": "Duration", "min": "PT30M", "max": "PT8H"},
"loanTerm": {"type": "Duration", "min": "P1Y", "max": "P30Y"}
}The simple form ("uptime": "Duration") uses the default PT0S-P1Y range.
Like other types, Duration can be marked symmetric on edges:
{
"edgeProperties": {
"totalCollaborationTime": {"type": "Duration", "min": "P7D", "max": "P3Y", "symmetric": true}
}
}Note: To draw a random value from the
min-maxrange, durations are reduced to seconds using fixed calendar approximations (1 year = 365 days, 1 month = 30 days, 1 week = 7 days). This is sufficient for synthetic data. Weeks (nW) are accepted inmin/maxbounds but never appear in generated values - e.g. aP2Wbound is treated as 14 days and a value of that length is rendered asP14D.
maxLength: Maximum number of characters (minimum: 5)
{
"description": {"type": "Text", "maxLength": 500}
}GQL-style uppercase type names are supported as aliases:
| Alias | Maps To |
|---|---|
STRING |
String |
INTEGER |
Int |
INT64 |
Int |
UINT64 |
Int |
FLOAT64 |
Float |
BOOLEAN |
Boolean |
BOOL |
Bool |
DATE |
Date |
DATETIME |
DateTime |
ZONED DATETIME |
DateTime |
DURATION |
Duration |
Edge properties can be marked as symmetric to ensure edges in both directions (A→B and B→A) share the same value:
{
"edgeProperties": {
"meetingDate": {"type": "Date", "symmetric": true},
"sharedProject": {"enum": ["Alpha", "Beta", "Gamma"], "symmetric": true}
}
}When an edge A→B is created and a reverse edge B→A already exists, symmetric properties are copied from the existing edge. This is useful for mutual relationships where both directions should have consistent values.
symmetric is only valid on edge properties - using it in nodeProperties is rejected during schema validation.
Properties that are calculated from the graph structure after generation:
{
"computedNodeProperties": {
"connectionCount": "degree"
}
}| Type | Description |
|---|---|
degree |
Total unique connections (undirected degree - counts both incoming and outgoing edges) |
Computed properties are added to nodes after all edges are generated, ensuring accurate values based on the final graph topology.
Ready-to-use example schemas are available in the schema-examples/ directory:
| File | Description |
|---|---|
simple_friendship_schema.json |
Person/friendOf - name, age |
simple_task_schema.json |
Task/dependsOn - title, status |
simple_webpage_schema.json |
Page/linksTo - url, title |
simple_message_schema.json |
User/messaged - username, email |
| File | Description |
|---|---|
default_schema.json |
Default Knows graph (Person/knows) |
social_network_schema.json |
Social media users and followers |
employee_schema.json |
Employee collaboration network |
ecommerce_schema.json |
E-commerce product relationships |
knowledge_graph_schema.json |
Knowledge graph with concepts |
citation_network_schema.json |
Academic paper citations |
transportation_schema.json |
Transit stations and routes |
financial_schema.json |
Bank accounts and transactions |
infrastructure_schema.json |
IT services and dependencies |
movie_database_schema.json |
Actor co-starring relationships |
Use them directly or as templates for your own schemas:
knows -n 50 -e 100 --schema schema-examples/social_network_schema.json
# or with Docker (using built-in example schemas)
docker run --rm lszeremeta/knows --schema /app/schema-examples/social_network_schema.json -n 50 -e 100knows --schema my_schema.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows --schema /data/my_schema.jsonknows -n 100 -e 200 --schema my_schema.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 100 -e 200 --schema /data/my_schema.json# GraphML
knows -n 50 -e 75 --schema my_schema.json -f graphml > graph.graphml
# or
knows -n 50 -e 75 --schema my_schema.json -f graphml graph.graphml
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f graphml > graph.graphml
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f graphml /data/graph.graphml
# Cypher (for Neo4j)
knows -n 50 -e 75 --schema my_schema.json -f cypher > graph.cypher
# or
knows -n 50 -e 75 --schema my_schema.json -f cypher graph.cypher
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f cypher > graph.cypher
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f cypher /data/graph.cypher
# CSV
knows -n 50 -e 75 --schema my_schema.json -f csv graph.csv
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f csv /data/graph.csv
# JSON
knows -n 50 -e 75 --schema my_schema.json -f json > graph.json
# or
knows -n 50 -e 75 --schema my_schema.json -f json graph.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f json > graph.json
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 50 -e 75 --schema /data/my_schema.json -f json /data/graph.jsonknows -n 20 -e 30 --schema my_schema.json -s 42
# or
docker run --rm -v "$(pwd)":/data lszeremeta/knows -n 20 -e 30 --schema /data/my_schema.json -s 42docker run --rm lszeremeta/knows --schema /app/schema-examples/social_network_schema.json -n 50 -e 100
# or
docker run --rm lszeremeta/knows --schema /app/schema-examples/employee_schema.json -n 20 -e 30 -f cypher- When using
--schema, the-np,-ep, and-apoptions are ignored - Schema files must be valid JSON with
.jsonextension - All property definitions are validated before graph generation
- Invalid schemas will produce clear error messages
- The schema format is inspired by GQL (ISO/IEC 39075) but is not a full GQL implementation