Who Am I

Who Am I?

  • Hi I'm Ryan.
  • I'm a community focused software Engineer currently working @ Bluetel (Huge thanks for allowing me to take the day to do this)
  • I help Co-organise codebar Birmingham
  • I have an unhealthy obsession with programming mascots 🐍 🐘 (JSON schema mascot coming when?)
  • Β 

I have no idea what I am doing

I have no idea what I am doing

Me

All the other speakers... and most of the people in the room

An I am here to talk about....

(if you are my older brother)

For the uninitiated

{
  "$schema": "http://json-schema.org/v1-coming-soon-πŸŽ‰πŸŽ‰πŸŽ‰/schema#",
  "title": "My Cool JSON Schema",
  "type": "object",
  "properties": {
    "what": {
      "type": "string"
    },
    "is": {
      "type": "number"
    },
    "a": {
      "enum": ["json", "schema"]
    },
   },
  "additionalProperties": false,
  "required": [
    "version"
  ]
}

For the uninitiated

{
  "$schema": "http://json-schema.org/v1-coming-soon-πŸŽ‰πŸŽ‰πŸŽ‰/schema#",
  "title": "My Cool JSON Schema",
  "type": "object",
  "properties": {
    "what": {
      "type": "string"
    },
    "is": {
      "type": "number"
    },
    "a": {
      "enum": ["json", "schema"]
    },
   },
  "additionalProperties": false,
  "required": [
    "version"
  ]
}
{
  "what": "foo",
  "is": 5,
  "a": "json"
}

For the uninitiated

{
  "$schema": "http://json-schema.org/v1-coming-soon-πŸŽ‰πŸŽ‰πŸŽ‰/schema#",
  "title": "My Cool JSON Schema",
  "type": "object",
  "properties": {
    "what": {
      "type": "string"
    },
    "is": {
      "type": "number"
    },
    "a": {
      "enum": ["json", "schema"]
    },
   },
  "additionalProperties": false,
  "required": [
    "version"
  ]
}
{
  "what": "foo",
  "is": 5,
  "a": "Invalid"
}

The Mission

Use this

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "My Cool JSON Schema",
  "type": "object",
  "properties": {
    "what": {
      "type": "string"
    },
    "is": {
      "type": "number"
    },
    "a": {
      "enum": ["json", "schema"]
    },
   },
  "additionalProperties": false,
  "required": [
    "version"
  ]
}
{
  "what": "foo",
  "is": 5,
  "a": "json"
}

To Generate this

Why?

{well}

{structured}

{data}

{yaaay}

{well}

{structured}

{data}

{yaaay}

:(

😭

2 YEARS

{Go Chaff}

How bad could it be...

Lets start with an easy one!

Easy!

{
  "type": "number"
}
4.5

Generate

Easy -ish

{
  "type": "integer"
}
5

Generate

Easy?

{
  "type": "integer",
  "minimum": 10
}
10

Generate

easy*

{
  "type": "integer",
  "exclusiveMinimum": 10
}
11

Generate

ᴇᴀsʏ

{
  "type": "integer",
  "multipleOf": 7,
  "exclusiveMinimum": 10
}
14

Generate

:(

{
  "type": "number",
  "multipleOf": 0.00324634,
  "exclusiveMinimum": 0.00634,
  "maximum": 0.086785345
}
🫠

Generate

Ok let's take a step back

maybe strings will be easier

{
  "type": "string"
}

Generate

"foo"
{
  "type": "string",
  "format": "time"
}

Generate

"???"

(Annotation as of latest draft)

{
  "type": "string",
  "format": "time"
}

Generate

"03:46:13+00:00"
{
  "type": "string",
  "pattern": "\w+"
}

oh no...

{
  "type": "string",
  "pattern": "\w+\d{0,1}"
}

oh no... please no...

{
  "type": "string",
  "pattern": "^(?=.{1,256})(?=.{1,64}@.{1,255}$)(?:(?![_.-])[a-zA-Z0-9._%+-]{1,64}(?:(?:(?<!\\)[.,;:])?(?=.{0,64})[a-zA-Z0-9._%+-]{0,64})?@(?:(?!-)[a-zA-Z0-9-]{1,63}(?:(?:(?<!\\)[.,;:])?(?=.{0,255})[a-zA-Z0-9-]{0,63})?\.?)+(?:(?!-)[a-zA-Z]{2,})?|(?:[a-zA-Z0-9-]{1,63}\.[a-zA-Z]{2,}))(?=.{1,256})(?=.{1,64}@.{1,255}$)(?:(?![_.-])[a-zA-Z0-9._%+-]{1,64}(?:(?:(?<!\\)[.,;:])?(?=.{0,64})[a-zA-Z0-9._%+-]{0,64})?@(?:(?!-)[a-zA-Z0-9-]{1,63}(?:(?:(?<!\\)[.,;:])?(?=.{0,255})[a-zA-Z0-9-]{0,63})?\.?)+(?:(?!-)[a-zA-Z]{2,})?|(?:[a-zA-Z0-9-]{1,63}\.[a-zA-Z]{2,}))(?=.{1,256})(?=.{1,64}@.{1,255}$)(?:(?![_.-])[a-zA-Z0-9._%+-]{1,64}(?:(?:(?<!\\)[.,;:])?(?=.{0,64})[a-zA-Z0-9._%+-]{0,64})?@(?:(?!-)[a-zA-Z0-9-]{1,63}(?:(?:(?<!\\)[.,;:])?(?=.{0,255})[a-zA-Z0-9-]{0,63})?\.?)+(?:(?!-)[a-zA-Z]{2,})?|(?:[a-zA-Z0-9-]{1,63}\.[a-zA-Z]{2,}))(?=.{1,256})(?=.{1,64}@.{1,255}$)(?:(?![_.-])[a-zA-Z0-9._%+-]{1,64}(?:(?:(?<!\\)[.,;:])?(?=.{0,64})[a-zA-Z0-9._%+-]{0,64})?@(?:(?!-)[a-zA-Z0-9-]{1,63}(?:(?:(?<!\\)[.,;:])?(?=.{0,255})[a-zA-Z0-9-]{0,63})?\.?)+(?:(?!-)[a-zA-Z]{2,})?|(?:[a-zA-Z0-9-]{1,63}\.[a-zA-Z]{2,}))$"
}

😭

Json's first scheme

Scheme 1: Constraints easy one direction...

{
	"type": "number",
    "multipleOf": 0.5,
    "minimum": 6
}
5

Is valid?

Scheme 1: Constraints easy one direction...

5
{"type": "number"}
{"multipleOf": 0.5}

βœ…

{"minimum": 6}

βœ…

βœ…

❌

Not Valid

Scheme 1: Constraints easy one direction... but not the other

???
{"type": "number"}
{"multipleOf": 0.5}
{"minimum": 6}
???
Β―\_(ツ)_/Β―

Anything!

Err... -1?

Err... -0.5?

Err 7 right?

How can we go about fixing this?

Compiling "Generators" ahead of time

{
	"type": "number",
    "multipleOf": 0.5,
    "minimum": 6
}
Random number generator:
 - Must Have number higher than 6
 - Must only generate in increments of 0.5
{
	"type": "object",
    "properties": {
    	"some_array": {
        	"type": "array",
            "minItems": 5,
            "items": {
            	"const": "test"
            }
        },
        "some_string": {
        	"minLength": 5
        }
    }
}

Then recursively building a tree of generatorsΒ 

Object Generator

"some_array"

Array Generator(Min Len: 5)

Then recursively building a tree of generatorsΒ 

Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Scheme 1: Constraints easy one direction... but not the other

Scheme 1: Constraints easy one direction... but not the other

So we are done right? πŸŽ‰

{
	"allOf": [
    	{
        	"type": "string",
            "minLength": 5
        },
        {
        	"format": "time"
        }
    ]
}

'allOf' the pain

scheme 2: Combination

scheme 2: Combination

scheme 2: Combination

πŸ€”

scheme 2: Combinators

😱

How can we work around this?

anyOf

{
	"anyOf": [
      {"type": "string"},
      {"type": "number"}
	]
}

anyOf

{
	"anyOf": [
      {"type": "string"},
      {"type": "number"}
	]
}
"yay"

βœ…

oneOf

{
	"oneOf": [
      {
      	"enum": ["foo", "baz"]
      },
      {
      	"enum": ["baz", "bar"]
      }
	]
}

oneOf

{
	"oneOf": [
      {
      	"enum": ["foo", "baz"]
      },
      {
      	"enum": ["baz", "bar"]
      }
	]
}

Generate

"baz"

oneOf

{
	"oneOf": [
      {
      	"enum": ["foo", "baz"]
      },
      {
      	"enum": ["baz", "bar"]
      }
	]
}
"baz"

Validate

oneOf

{
	"oneOf": [
      {
      	"enum": ["foo", "baz"]
      },
      {
      	"enum": ["baz", "bar"]
      }
	]
}

Generate

"foo"

Repeat if not valid
(up to a limit)

allOf

{
	"allOf": [
     	{
        	"minLength": "5"
        },
        {
        	"type": "string"
        }
	]
}

allOf

"allOf": [
  {
  "minimumLength": "5"
  },
  {
  "type": "string"
  }
]

"type": "string",
"minimumLength": 5,

Merge

allOf

"allOf": [
  {
  "minimumLength": "5"
  },
  {
  "type": "string"
  }
]

"type": "string",
"minimumLength": 5,

Merge

Generate

"Heloooo"

Easy right....?

allOf: Err what about this?

{
	"allOf": [
        {"type": "integer"},
        {"multipleOf": 8},
        {"multipleOf": 14},
        {"minimum": 20},
        {"exclusiveMinimum": 55},
        {"maximum": 600}
    ]
}

allOf: Custom Merge algorithm

{
   "exclusiveMinimum" : 55,
   "maximum" : 600,
   "minimum" : 20,
   "multipleOf" : 112,
   "type" : "integer"
}
Make the most restrictive intersection of all given nodes

scheme 2: Combinators

scheme 2: Combinators

Ok so we are done right... right?

{
   "$ref": "https://despair.com/hahah.json#/nope"
}

Is that URL

IS THAT A URL

Scheme 3: $refusing to accept defeat

{
    "$schema": "http://json-schema.org/draft-9001/schema#",
    "type": "object",
    "properties": {
        "who_would_be_silly_enough_to_make_a_json_schem_faker": {
            "$ref": "#/$defs/me"
        }
    },
    "$defs": {
        "me": {
            "properties": {
            	"pain": {"const": "owwww"},
                "suffering": {"const": "ouchie"}
            },
            "required": ["pain", "suffering"]
        }
    }
}

Scheme 3: $refusing to accept defeat

Reference Generator
#/$defs/me/properties/suffering ConstGenerator: "Oww"
#/$defs/me/properties/pain ConstGenerator: "Suffering"
#/$defs/me ObjectGenerator
#/properties/who_would_be_silly_enough_to_make_a_json_schem_faker ReferenceGenerator: "#/$defs/me"
# Root Generator

Scheme 3: It's time to write a web crawlerπŸ•·οΈ

{
    "type": "object",
    "properties": {
        "who_would_be_silly_enough_to_make_a_json_schem_faker": {
            "$ref": "http://www.example.com#/$defs/me"
        }
    }
}
# http://www.example.com
{
    "$defs": {
        "me": {
            "properties": {
            	"pain": {"const": "owwww"},
                "suffering": {"const": "ouchie"}
            }
            "required": ["pain", "suffering"]
        }
    }
}

Scheme 3: It's time to write a web crawlerπŸ•·οΈ

Reference Generator
#/properties/who_would_be_silly_enough_to_make_a_json_schem_faker ReferenceGenerator: "http://www.example.com#/$defs/me"
# Root Generator
Reference Generator
#/$defs/me/properties/suffering ConstGenerator: "Oww"
#/$defs/me/properties/pain ConstGenerator: "Suffering"
#/$defs/me ObjectGenerator
# Root Generator

www.example.com

Root Document

Scheme 3: It's time to write a web crawlerπŸ•·οΈ

Reference Generator
#/properties/who_would_be_silly_enough_to_make_a_json_schem_faker ReferenceGenerator: "http://www.example.com#/$defs/me"
# Root Generator
Reference Generator
#/$defs/me/properties/suffering ConstGenerator: "Oww"
#/$defs/me/properties/pain ConstGenerator: "Suffering"
#/$defs/me ObjectGenerator
# Root Generator

www.example.com

Root Document

Scheme 3: $ref...

{
  "type": "object",
  "properties": {
    "value": { "type": "string" },
    "next": { "$ref": "#/" }
  }
}

Scheme 3: $ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$ref$

{
  "type": "object",
  "properties": {
    "value": { "type": "string" },
    "next": { "$ref": "#/" }
  }
}

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 0
Max Effort: 5

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 1

Max Effort: 5

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 2

Max Effort: 5

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 3

Max Effort: 5

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 4

Max Effort: 5

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 5

Max Effort: 5

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 5

Max Effort: 5

Β―\_(ツ)_/Β―

Scheme 3: Circular References

an asside on complexity

Object Generator

"some_array"

Array Generator(Min Len: 5)
Constant Generator: "test"
String Generator
(min len: 5)

"some_string"

Generation Effort: 5

Max Effort: 5

Return

Scheme 3: Circular References

However when we need to merge

{
	"allOf": [
        {"$ref": "#/someCircularRef"}
    ]
}

Scheme 3: Circular References

However when we need to merge

{
  "$id": "node",
  "type": "object",
  "properties": {
    "value": { "type": "string" },
    "next": {
      "type": "object",
      "properties": {
        "value": { "type": "string" },
        "next": {
          "type": "object",
          "properties": {
            "value": { "type": "string" },
            "next": {
              "type": "object",
              "properties": {
                "value": { "type": "string" },
                "next": {
                  "type": "object",
                  "properties": {
                    "value": { "type": "string" },
                    "next": {
                      "type": "object",
                      "properties": {
                        "value": { "type": "string" },
                        "next": {
                          "type": "object",
                          "properties": {
                            "value": { "type": "string" },
                            "next": {
                              "type": "object",
                              "properties": {
                                "value": { "type": "string" },
                                "next": {
                                  "type": "object",
                                  "properties": {
                                    "value": { "type": "string" },
                                    "next": {
                                      "type": "object",
                                      "properties": {
                                        "value": { "type": "string" },
                                        "next": {
                                          "type": "object",
                                          "properties": {
                                            "value": { "type": "string" },
                                            "next": {
                                              "type": "object",
                                              "properties": {
                                                "value": { "type": "string" },
                                                "next": {
                                                  "type": "object",
                                                  "properties": {
                                                    "value": { "type": "string" },
                                                    "next": {
                                                      "type": "object",
                                                      "properties": {
                                                        "value": { "type": "string" },
                                                        "next": {
                                                          "type": "object",
                                                          "properties": {
                                                            "value": { "type": "string" },
                                                            "next": {
                                                              "type": "object",
                                                              "properties": {
                                                                "value": { "type": "string" },
                                                                "next": {
                                                                  "type": "object",
                                                                  "properties": {
                                                                    "value": { "type": "string" },
                                                                    "next": {
                                                                      "type": "object",
                                                                      "properties": {
                                                                        "value": { "type": "string" },
                                                                        "next": {
                                                                          "type": "object",
                                                                          "properties": {
                                                                            "value": { "type": "string" },
                                                                            "next": {
                                                                              "type": "object",
                                                                              "properties": {
                                                                                "value": { "type": "string" },
                                                                                "next": {
                                                                                  "type": "object",
                                                                                  "properties": {
                                                                                    "value": { "type": "string" },
                                                                                    "next": {
                                                                                      "type": "object",
                                                                                      "properties": {
                                                                                        "value": { "type": "string" },
                                                                                        "next": {
                                                                                          "type": "object",
                                                                                          "properties": {
                                                                                            "value": { "type": "string" },
                                                                                            "next": {
                                                                                              "type": "object",
                                                                                              "properties": {
                                                                                                "value": { "type": "string" },
                                                                                                "next": {
                                                                                                  "type": "object",
                                                                                                  "properties": {
                                                                                                    "value": { "type": "string" },
                                                                                                    "next": {
                                                                                                      "type": "object",
                                                                                                      "properties": {
                                                                                                        "value": { "type": "string" },
                                                                                                        "next": {
                                                                                                          "type": "object",
                                                                                                          "properties": {
                                                                                                            "value": { "type": "string" },
                                                                                                            "next": {
                                                                                                              "type": "object",
                                                                                                              "properties": {
                                                                                                                "value": { "type": "string" },
                                                                                                                "next": {
                                                                                                                  "type": "object",
                                                                                                                  "properties": {
                                                                                                                    "value": { "type": "string" },
                                                                                                                    "next": {
                                                                                                                      "type": "object",
                                                                                                                      "properties": {
                                                                                                                        "value": { "type": "string" },
                                                                                                                        "next": {
                                                                                                                          "type": "object",
                                                                                                                          "properties": {
                                                                                                                            "value": { "type": "string" },
                                                                                                                            "next": {
                                                                                                                              "type": "object",
                                                                                                                              "properties": {
                                                                                                                                "value": { "type": "string" },
                                                                                                                                "next": {
                                                                                                                                  "type": "object",
                                                                                                                                  "properties": {
                                                                                                                                    "value": { "type": "string" },
                                                                                                                                    "next": {
                                                                                                                                      "type": "object",
                                                                                                                                      "properties": {
                                                                                                                                        "value": { "type": "string" },
                                                                                                                                        "next": {
                                                                                                                                          "type": "object",
                                                                                                                                          "properties": {
                                                                                                                                            "value": { "type": "string" },
                                                                                                                                            "next": {
                                                                                                                                              "type": "object",
                                                                                                                                              "properties": {
                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                "next": {
                                                                                                                                                  "type": "object",
                                                                                                                                                  "properties": {
                                                                                                                                                    "value": { "type": "string" },
                                                                                                                                                    "next": {
                                                                                                                                                      "type": "object",
                                                                                                                                                      "properties": {
                                                                                                                                                        "value": { "type": "string" },
                                                                                                                                                        "next": {
                                                                                                                                                          "type": "object",
                                                                                                                                                          "properties": {
                                                                                                                                                            "value": { "type": "string" },
                                                                                                                                                            "next": {
                                                                                                                                                              "type": "object",
                                                                                                                                                              "properties": {
                                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                                "next": {
                                                                                                                                                                  "type": "object",
                                                                                                                                                                  "properties": {
                                                                                                                                                                    "value": { "type": "string" },
                                                                                                                                                                    "next": {
                                                                                                                                                                      "type": "object",
                                                                                                                                                                      "properties": {
                                                                                                                                                                        "value": { "type": "string" },
                                                                                                                                                                        "next": {
                                                                                                                                                                          "type": "object",
                                                                                                                                                                          "properties": {
                                                                                                                                                                            "value": { "type": "string" },
                                                                                                                                                                            "next": {
                                                                                                                                                                              "type": "object",
                                                                                                                                                                              "properties": {
                                                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                                                "next": {
                                                                                                                                                                                  "type": "object",
                                                                                                                                                                                  "properties": {
                                                                                                                                                                                    "value": { "type": "string" },
                                                                                                                                                                                    "next": {
                                                                                                                                                                                      "type": "object",
                                                                                                                                                                                      "properties": {
                                                                                                                                                                                        "value": { "type": "string" },
                                                                                                                                                                                        "next": {
                                                                                                                                                                                          "type": "object",
                                                                                                                                                                                          "properties": {
                                                                                                                                                                                            "value": { "type": "string" },
                                                                                                                                                                                            "next": {
                                                                                                                                                                                              "type": "object",
                                                                                                                                                                                              "properties": {
                                                                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                                                                "next": "..."
                                                                                                                                                                                              }
                                                                                                                                                                                            }
                                                                                                                                                                                          }
                                                                                                                                                                                        }
                                                                                                                                                                                      }
                                                                                                                                                                                    }
                                                                                                                                                                                  }
                                                                                                                                                                                }
                                                                                                                                                                              }
                                                                                                                                                                            }
                                                                                                                                                                          }
                                                                                                                                                                        }
                                                                                                                                                                      }
                                                                                                                                                                    }
                                                                                                                                                                  }
                                                                                                                                                                }
                                                                                                                                                              }
                                                                                                                                                            }
                                                                                                                                                          }
                                                                                                                                                        }
                                                                                                                                                      }
                                                                                                                                                    }
                                                                                                                                                  }
                                                                                                                                                }
                                                                                                                                              }
                                                                                                                                            }
                                                                                                                                          }
                                                                                                                                        }
                                                                                                                                      }
                                                                                                                                    }
                                                                                                                                  }
                                                                                                                                }
                                                                                                                              }
                                                                                                                            }
                                                                                                                          }
                                                                                                                        }
                                                                                                                      }
                                                                                                                    }
                                                                                                                  }
                                                                                                                }
                                                                                                              }
                                                                                                            }
                                                                                                          }
                                                                                                        }
                                                                                                      }
                                                                                                    }
                                                                                                  }
                                                                                                }
                                                                                              }
                                                                                            }
                                                                                          }
                                                                                        }
                                                                                      }
                                                                                    }
                                                                                  }
                                                                                }
                                                                              }
                                                                            }
                                                                          }
                                                                        }
                                                                      }
                                                                    }
                                                                  }
                                                                }
                                                              }
                                                            }
                                                          }
                                                        }
                                                      }
                                                    }
                                                  }
                                                }
                                              }
                                            }
                                          }
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Scheme 3: Circular References

However when we need to merge

{
  "$id": "node",
  "type": "object",
  "properties": {
    "value": { "type": "string" },
    "next": {
      "type": "object",
      "properties": {
        "value": { "type": "string" },
        "next": {
          "type": "object",
          "properties": {
            "value": { "type": "string" },
            "next": {
              "type": "object",
              "properties": {
                "value": { "type": "string" },
                "next": {
                  "type": "object",
                  "properties": {
                    "value": { "type": "string" },
                    "next": {
                      "type": "object",
                      "properties": {
                        "value": { "type": "string" },
                        "next": {
                          "type": "object",
                          "properties": {
                            "value": { "type": "string" },
                            "next": {
                              "type": "object",
                              "properties": {
                                "value": { "type": "string" },
                                "next": {
                                  "type": "object",
                                  "properties": {
                                    "value": { "type": "string" },
                                    "next": {
                                      "type": "object",
                                      "properties": {
                                        "value": { "type": "string" },
                                        "next": {
                                          "type": "object",
                                          "properties": {
                                            "value": { "type": "string" },
                                            "next": {
                                              "type": "object",
                                              "properties": {
                                                "value": { "type": "string" },
                                                "next": {
                                                  "type": "object",
                                                  "properties": {
                                                    "value": { "type": "string" },
                                                    "next": {
                                                      "type": "object",
                                                      "properties": {
                                                        "value": { "type": "string" },
                                                        "next": {
                                                          "type": "object",
                                                          "properties": {
                                                            "value": { "type": "string" },
                                                            "next": {
                                                              "type": "object",
                                                              "properties": {
                                                                "value": { "type": "string" },
                                                                "next": {
                                                                  "type": "object",
                                                                  "properties": {
                                                                    "value": { "type": "string" },
                                                                    "next": {
                                                                      "type": "object",
                                                                      "properties": {
                                                                        "value": { "type": "string" },
                                                                        "next": {
                                                                          "type": "object",
                                                                          "properties": {
                                                                            "value": { "type": "string" },
                                                                            "next": {
                                                                              "type": "object",
                                                                              "properties": {
                                                                                "value": { "type": "string" },
                                                                                "next": {
                                                                                  "type": "object",
                                                                                  "properties": {
                                                                                    "value": { "type": "string" },
                                                                                    "next": {
                                                                                      "type": "object",
                                                                                      "properties": {
                                                                                        "value": { "type": "string" },
                                                                                        "next": {
                                                                                          "type": "object",
                                                                                          "properties": {
                                                                                            "value": { "type": "string" },
                                                                                            "next": {
                                                                                              "type": "object",
                                                                                              "properties": {
                                                                                                "value": { "type": "string" },
                                                                                                "next": {
                                                                                                  "type": "object",
                                                                                                  "properties": {
                                                                                                    "value": { "type": "string" },
                                                                                                    "next": {
                                                                                                      "type": "object",
                                                                                                      "properties": {
                                                                                                        "value": { "type": "string" },
                                                                                                        "next": {
                                                                                                          "type": "object",
                                                                                                          "properties": {
                                                                                                            "value": { "type": "string" },
                                                                                                            "next": {
                                                                                                              "type": "object",
                                                                                                              "properties": {
                                                                                                                "value": { "type": "string" },
                                                                                                                "next": {
                                                                                                                  "type": "object",
                                                                                                                  "properties": {
                                                                                                                    "value": { "type": "string" },
                                                                                                                    "next": {
                                                                                                                      "type": "object",
                                                                                                                      "properties": {
                                                                                                                        "value": { "type": "string" },
                                                                                                                        "next": {
                                                                                                                          "type": "object",
                                                                                                                          "properties": {
                                                                                                                            "value": { "type": "string" },
                                                                                                                            "next": {
                                                                                                                              "type": "object",
                                                                                                                              "properties": {
                                                                                                                                "value": { "type": "string" },
                                                                                                                                "next": {
                                                                                                                                  "type": "object",
                                                                                                                                  "properties": {
                                                                                                                                    "value": { "type": "string" },
                                                                                                                                    "next": {
                                                                                                                                      "type": "object",
                                                                                                                                      "properties": {
                                                                                                                                        "value": { "type": "string" },
                                                                                                                                        "next": {
                                                                                                                                          "type": "object",
                                                                                                                                          "properties": {
                                                                                                                                            "value": { "type": "string" },
                                                                                                                                            "next": {
                                                                                                                                              "type": "object",
                                                                                                                                              "properties": {
                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                "next": {
                                                                                                                                                  "type": "object",
                                                                                                                                                  "properties": {
                                                                                                                                                    "value": { "type": "string" },
                                                                                                                                                    "next": {
                                                                                                                                                      "type": "object",
                                                                                                                                                      "properties": {
                                                                                                                                                        "value": { "type": "string" },
                                                                                                                                                        "next": {
                                                                                                                                                          "type": "object",
                                                                                                                                                          "properties": {
                                                                                                                                                            "value": { "type": "string" },
                                                                                                                                                            "next": {
                                                                                                                                                              "type": "object",
                                                                                                                                                              "properties": {
                                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                                "next": {
                                                                                                                                                                  "type": "object",
                                                                                                                                                                  "properties": {
                                                                                                                                                                    "value": { "type": "string" },
                                                                                                                                                                    "next": {
                                                                                                                                                                      "type": "object",
                                                                                                                                                                      "properties": {
                                                                                                                                                                        "value": { "type": "string" },
                                                                                                                                                                        "next": {
                                                                                                                                                                          "type": "object",
                                                                                                                                                                          "properties": {
                                                                                                                                                                            "value": { "type": "string" },
                                                                                                                                                                            "next": {
                                                                                                                                                                              "type": "object",
                                                                                                                                                                              "properties": {
                                                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                                                "next": {
                                                                                                                                                                                  "type": "object",
                                                                                                                                                                                  "properties": {
                                                                                                                                                                                    "value": { "type": "string" },
                                                                                                                                                                                    "next": {
                                                                                                                                                                                      "type": "object",
                                                                                                                                                                                      "properties": {
                                                                                                                                                                                        "value": { "type": "string" },
                                                                                                                                                                                        "next": {
                                                                                                                                                                                          "type": "object",
                                                                                                                                                                                          "properties": {
                                                                                                                                                                                            "value": { "type": "string" },
                                                                                                                                                                                            "next": {
                                                                                                                                                                                              "type": "object",
                                                                                                                                                                                              "properties": {
                                                                                                                                                                                                "value": { "type": "string" },
                                                                                                                                                                                                "next": "..."
                                                                                                                                                                                              }
                                                                                                                                                                                            }
                                                                                                                                                                                          }
                                                                                                                                                                                        }
                                                                                                                                                                                      }
                                                                                                                                                                                    }
                                                                                                                                                                                  }
                                                                                                                                                                                }
                                                                                                                                                                              }
                                                                                                                                                                            }
                                                                                                                                                                          }
                                                                                                                                                                        }
                                                                                                                                                                      }
                                                                                                                                                                    }
                                                                                                                                                                  }
                                                                                                                                                                }
                                                                                                                                                              }
                                                                                                                                                            }
                                                                                                                                                          }
                                                                                                                                                        }
                                                                                                                                                      }
                                                                                                                                                    }
                                                                                                                                                  }
                                                                                                                                                }
                                                                                                                                              }
                                                                                                                                            }
                                                                                                                                          }
                                                                                                                                        }
                                                                                                                                      }
                                                                                                                                    }
                                                                                                                                  }
                                                                                                                                }
                                                                                                                              }
                                                                                                                            }
                                                                                                                          }
                                                                                                                        }
                                                                                                                      }
                                                                                                                    }
                                                                                                                  }
                                                                                                                }
                                                                                                              }
                                                                                                            }
                                                                                                          }
                                                                                                        }
                                                                                                      }
                                                                                                    }
                                                                                                  }
                                                                                                }
                                                                                              }
                                                                                            }
                                                                                          }
                                                                                        }
                                                                                      }
                                                                                    }
                                                                                  }
                                                                                }
                                                                              }
                                                                            }
                                                                          }
                                                                        }
                                                                      }
                                                                    }
                                                                  }
                                                                }
                                                              }
                                                            }
                                                          }
                                                        }
                                                      }
                                                    }
                                                  }
                                                }
                                              }
                                            }
                                          }
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Scheme 3: Circular References

If you have any idea how this might be resolvable please let me know! *
(Tell me I am silly!)
Β 

*(Currently in the process of looking into the approach used in https://github.com/udamir/allof-merge)

Scheme 3: $refs

Scheme 3: $refs

Please no more

scheme 2: Combination

scheme 2: Combination

scheme 2: Combination

scheme 2: Combination

Scheme 4: NOT

scheme 2: Combination

Scheme 4: NOT

My sanity

!

One Exclamation mark boi

scheme 2: Combination

Scheme 4: NOT

from a validators perspective

{
	"not": {
    	"multipleOf": 5
    }
}

scheme 2: Combination

Scheme 4: NOT

from a validators perspective

{
	"not": {
    	"multipleOf": 5
    }
}

Validate Against

scheme 2: Combination

Scheme 4: NOT

from a validators perspective
easy :)

Β 

{
	"not": {
    	"multipleOf": 5
    }
}

Validate Against

Invert result :)

scheme 2: Combination

Scheme 4: NOT

{
    "minimum": 45,
    "exclusiveMaximum": 64,
    "multipleOf": 7,
    "not": {
        "exclusiveMinimum": 48,
        "maximum": 55,
        "multipleOf": 14
    }
}

From a generators perspective.
Just find the number easy :)

scheme 2: Combination

Scheme 4: Do it all again... backwards

func resolveBoundsFloat64(metadata *parserMetadata,
	minFieldName string,
	maxFieldName string,
	minPtr *float64, minExclusivePtr *float64,
	maxPtr *float64, maxExclusivePtr *float64,
	notMinPtr *float64, notMinExclusivePtr *float64,
	notMaxPtr *float64, notMaxExclusivePtr *float64,
	offsetIncrement float64,
) (*float64, *float64, *float64, *float64)

scheme 2: Combination

Scheme 4: notMerging

  • Merge what we can by logically resolving constraints inside and outside of the not.
  • Apply constraints to the output of the generated output where not possible and brute force generate for a number of different iterations.

scheme 2: Combination

Scheme 4: notMerging

{
    "enum": [
        "foo", "baz", "bar"
    ],
    "not": {
        "enum": ["baz", "bar"]
    }
}

scheme 2: Combination

Scheme 4: notMerging

{
    "enum": [
        "foo", "baz", "bar"
    ],
    "not": {
        "enum": ["baz", "bar"]
    }
}
{
	"const": "foo"
}

Simplifies to

scheme 2: Combination

Scheme 4: notMerging

{
    "minimum": 45,
    "exclusiveMaximum": 64,
    "multipleOf": 7,
    "not": {
        "exclusiveMinimum": 48,
        "maximum": 55,
        "multipleOf": 14
    }
}

scheme 2: Combination

Scheme 4: notMerging

{
    "minimum": 45,
    "exclusiveMaximum": 64,
    "multipleOf": 7,
    "not": {
        "exclusiveMinimum": 48,
        "maximum": 55,
        "multipleOf": 14
    }
}
{
	"const": 63
}

Simplifies to

scheme 2: Combination

Scheme 4: Not not

{
    "not": {
        "not": {
            "not": {
                "not": {
                    "not": {
                        "type": "object",
                        "required": ["children"]
                    }
                }
            }
        }
    }
}

scheme 2: Combination

Scheme 4: Not not

{ 
    "not": {
        "not": {
            "type": "object",
            "required": ["children"]
        }
    }     
}

scheme 2: Combination

Scheme 4: Not not

{ 
    "not": {
        "not": {
            "type": "object",
            "required": ["children"]
        }
    }     
}

Is Equal To

{
	"type": "object",
	"required": ["children"]
}

scheme 2: Combination

Scheme 4: Not not

{
    "not": {
        "not": {
            "not": {
                "not": {
                    "not": {
                        "type": "object",
                        "required": ["children"]
                    }
                }
            }
        }
    }
}

Merge alternating (excluding not)

using the allOf merge algorithm, leaving a single node and notNode

Scheme 4: not

Scheme 4: not

Still need to resolve merging for `if`, `then`, `else`, `oneOf`, `allOf`, `anyOf`

Anything else?

Anything else?

{
	"mimimum": 20,
    "maximum: 10
}

Anything else?

{
	"mimimum": 20,
    "maximum": 10
}

wat?

Anything else?

{
	"mimimum": 20,
    "maximum": 10
}

Scheme 5: where logic breaks down...

{"mimimum": 20}
{"maximum": 10}
15

Scheme 5: where logic breaks down...

βœ…

{"mimimum": 20}
{"maximum": 10}
15

Scheme 5: where logic breaks down...

βœ…

{"mimimum": 20}
{"maximum": 10}
15

Scheme 5: where logic breaks down...

βœ…

❌

Not valid

15

Scheme 5: where logic breaks down...

for a generator

{
	"mimimum": 20,
    "maximum": 10
}

Error? Null?

Scheme 5: where logic breaks down...

To really exemplify the point lets have a quiz

Note that for the purposes of this quiz an "Illogical schema" is one where traits of the schema invalidate each other. Or we could not pass in data other than an empty value to satisfy the schema.


Β 

(If I have missed anything assume you need to match all the constraints given to have the schema validate)

Is the schema illogical?

{
	"pattern": "\\d+\\w{2}",
    "maxLength": 3
}

Is the schema illogical?

{
	"pattern": "\\d+\\w{2}",
    "maxLength": 3
}

Logical βœ…

Matches at min a 3 char sequence

Matches up to 3 chars

Is the schema illogical?

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "not": {
    	"minimum": 9999
    }
}

Is the schema illogical?

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "not": {
    	"minimum": 9999
    }
}

Is the schema illogical?

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "not": {
    	"minimum": 9999
    }
}

Illogical ❌

Is the schema illogical?

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "maximum": 9999
}

Illogical ❌

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "not": {
    	"minimum": 9999
    }
}

Simplifies To

Is the schema illogical?

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "maximum": 9999
}

Illogical ❌

Smallest possible integer multiple 9999

Is the schema illogical?

{
	"type": "integer",
    "multipleOf": 0.9999,
    "mimimum": 0,
    "maximum": 9999
}

Illogical ❌

Smallest possible integer multiple 9999

Not valid against
("exclusiveMaximim" would)

Is the schema illogical?

{
  "type": "array",
  "allOf": [
    {
      "items": {
        "enum": [
          "foo",
          "baz"
        ]
      },
    },
    {
      "items": {
        "const": "foo",
      }
    },
    {
      "items": {
      	"const": "baz"
      }
    }
  ]
}

Is the schema illogical?

Illogical ❌

{
  "type": "array",
  "allOf": [
    {
      "items": {
        "enum": [
          "foo",
          "baz"
        ]
      },
    },
    {
      "items": {
        "const": "foo",
      }
    },
    {
      "items": {
      	"const": "baz"
      }
    }
  ]
}

Is the schema illogical?

{
  "type": "array",
  "allOf": [
    {
      "items": {
        "enum": [
          "foo",
          "baz"
        ]
      },
    },
    {
      "items": {
        "const": "foo",
      }
    },
    {
      "items": {
      	"const": "baz"
      }
    }
  ]
}

Illogical ❌

Mutually exclusive

Is the schema illogical?

{
  "$ref": "#/$defs/node",
  "$defs": {
    "node": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "children": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/node"
          }
        },
      },
        "required": [
          "children"
        ]
    }
  }
}

Text

Is the schema illogical?

{
  "$ref": "#/$defs/node",
  "$defs": {
    "node": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "children": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/node"
          }
        },
      },
        "required": [
          "children"
        ]
    }
  }
}

Illogical ❌

Text

Is the schema illogical?

{
  "$ref": "#/$defs/node",
  "$defs": {
    "node": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "children": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/node"
          }
        },
      },
        "required": [
          "children"
        ]
    }
  }
}

Illogical ❌

Text

Forces infinite
recursion

Scheme 5: Illogical Schemas

What we can do about this?

  • Given we are already compiling the schema into an intermediary generator tree we can:
    • Validate certain logical constraints during compilation.Β 
    • In cases where schema traversal is required mixing earlier talked about cost functions with cyclic reference checks
    • Setting a maximum reference resolution depth during generation

Scheme 5: Illogical Schemas

Scheme 5: Illogical Schemas

As we go forwards

There are a few other things:

  • if/then/else clauses are fairly difficult to resolve during merging and have a number of different bugs
  • Some verbiage from newer schema drafts needs to be implemented $dynamicReference, $depentantProperties, ect...
  • Not has restrictions.
  • Mixing of certain properties like "pattern" and "format" (In assertion mode) can be fairly difficult to reconcile. Or "pattern" with "min/maxLength" due to enforcing one verses the other.

Why Bother using a JSON schema faker?

Testing

JSON Schema Faker

Testing

JSON Schema Faker

JSON Schema Validator

Testing

Generate

Validate

JSON Schema Faker

X100

JSON Schema Validator

Testing

Generate

Validate

JSON Schema Faker

X100

JSON Schema Validator (s)

Testing for differences by fuzzing

βœ…

βœ…

βœ…

❌

Exploring Your Schemas

{
	"properties": {
    	"sometimes_schemas": {
        	"const": "can be very complex"
        }
    }
}
{"sometimes_schemas":"can be very complex"}

Having a JSON schema faker generate many samples can be a great way of understanding what a schema is looking for or find issues withΒ 

Test Mocks

The original use case was a need for high quality random data, something JSON schema is set to do really well as it already aims to cover the shape of pretty much any structured data format.

Β 

This is one of the main reasons for using json schema

{schema}

{data}

🚨You have gone more than 15 minutes without talking about AI🚨

Why Not Use AI?

*

* For the problem:
"Generate random JSON to satisfy a given JSON schema"

Caveat .txtΒ are trying to solve fundamentally a different problem in a really cool way

Caveat .txtΒ are trying to solve fundamentally a different problem in a really cool way

Only speak with this JSON schema

Caveat .txtΒ are trying to solve fundamentally a different problem in a really cool way

Only speak with this JSON schema

{
	"structured": "data",
    "with": "purpose"
}

- MCP

- Anything that really requires well structure data

Feed into

Why Not Use AI?

Bad Output

[More bugs to fix yaaay]

use .txt, use a larger model Β―\_(ツ)_/Β―?

Bad Output

Why Not Use AI?

100x faster

Whats Next

  • Feature selection needs to be configurable based on a given JSON Schema draft
  • Many many many small edge cases surrounding bad merges need to be resolved and a respect that not all constraints can be reasonably resolved together.Β 
  • Ideally all schema vocabulary will be supported or explicitly disallowed in combination.

Credits

- Β Mascot design by @Iroshi_ CC0

- Most other Images CC0 Wikimedia commons

Β 

https://github.com/ryanolee/go-chaff
Bugs and PR's always appreciated :)

Contributions

Thank you and Questions?

Go Chaff

By Rizza

Go Chaff

  • 83