Who Am I?
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
(if you are my older brother)
{
"$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"
]
}{
"$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"
}{
"$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"
}{
"$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"
}{well}
{structured}
{data}
{yaaay}
{well}
{structured}
{data}
{yaaay}
2 YEARS
{Go Chaff}
{
"type": "number"
}4.5Generate
{
"type": "integer"
}5Generate
{
"type": "integer",
"minimum": 10
}10Generate
{
"type": "integer",
"exclusiveMinimum": 10
}11Generate
α΄α΄sΚ
{
"type": "integer",
"multipleOf": 7,
"exclusiveMinimum": 10
}14Generate
:(
{
"type": "number",
"multipleOf": 0.00324634,
"exclusiveMinimum": 0.00634,
"maximum": 0.086785345
}π« Generate
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
}5Is 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?
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
}
}
}Object Generator
"some_array"
Array Generator(Min Len: 5)
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
{
"allOf": [
{
"type": "string",
"minLength": 5
},
{
"format": "time"
}
]
}π±
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
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)
Please no more
Scheme 4: NOT
Scheme 4: NOT
My sanity
!
One Exclamation mark boi
Scheme 4: NOT
from a validators perspective
{
"not": {
"multipleOf": 5
}
}Scheme 4: NOT
from a validators perspective
{
"not": {
"multipleOf": 5
}
}Validate Against
Scheme 4: NOT
from a validators perspective
easy :)
Β
{
"not": {
"multipleOf": 5
}
}Validate Against
Invert result :)
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 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 4: notMerging
Scheme 4: notMerging
{
"enum": [
"foo", "baz", "bar"
],
"not": {
"enum": ["baz", "bar"]
}
}Scheme 4: notMerging
{
"enum": [
"foo", "baz", "bar"
],
"not": {
"enum": ["baz", "bar"]
}
}{
"const": "foo"
}Simplifies to
Scheme 4: notMerging
{
"minimum": 45,
"exclusiveMaximum": 64,
"multipleOf": 7,
"not": {
"exclusiveMinimum": 48,
"maximum": 55,
"multipleOf": 14
}
}Scheme 4: notMerging
{
"minimum": 45,
"exclusiveMaximum": 64,
"multipleOf": 7,
"not": {
"exclusiveMinimum": 48,
"maximum": 55,
"multipleOf": 14
}
}{
"const": 63
}Simplifies to
Scheme 4: Not not
{
"not": {
"not": {
"not": {
"not": {
"not": {
"type": "object",
"required": ["children"]
}
}
}
}
}
}Scheme 4: Not not
{
"not": {
"not": {
"type": "object",
"required": ["children"]
}
}
}Scheme 4: Not not
{
"not": {
"not": {
"type": "object",
"required": ["children"]
}
}
}Is Equal To
{
"type": "object",
"required": ["children"]
}
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}15Scheme 5: where logic breaks down...
β
{"mimimum": 20}{"maximum": 10}15Scheme 5: where logic breaks down...
β
{"mimimum": 20}{"maximum": 10}15Scheme 5: where logic breaks down...
β
β
Not valid
15Scheme 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?
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$dynamicReference, $depentantProperties, ect...
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
- Β Mascot design by @Iroshi_ CC0
- Most other Images CC0 Wikimedia commons
Β
https://github.com/ryanolee/go-chaff
Bugs and PR's always appreciated :)