Skip to content

Commit

Permalink
[Feature] Constant elements in JSON schemas (#886)
Browse files Browse the repository at this point in the history
This is a super quick PR as I work toward supporting some large JSON
schemas I'm working with. All it does is support the `const` keyword in
JSON schemas, which are a way of hard coding constant elements:
https://json-schema.org/understanding-json-schema/reference/const
  • Loading branch information
wjn0 authored Jun 6, 2024
1 parent 325b2c8 commit 14862a1
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
4 changes: 4 additions & 0 deletions guidance/library/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ def _gen_json(
reference=json_schema[REF_STRING], definitions=definitions
)

CONST_STRING = "const"
if CONST_STRING in json_schema:
return lm + _to_compact_json(json_schema[CONST_STRING])

ENUM_STRING = "enum"
if ENUM_STRING in json_schema:
return lm + _process_enum(options=json_schema["enum"])
Expand Down
59 changes: 59 additions & 0 deletions tests/library/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,65 @@ def test_bad_prefix_enum(self, bad_obj, good_bytes, failure_byte, allowed_bytes)
)


class TestConst:
def test_constant_int(self):
# First sanity check what we're setting up
schema_obj = {"const": 1}
target_obj = 1
validate(instance=target_obj, schema=schema_obj)

# The actual check
generate_and_check(target_obj, schema_obj)

def test_constant_string(self):
# First sanity check what we're setting up
schema_obj = {"const": "hello"}
target_obj = "hello"
validate(instance=target_obj, schema=schema_obj)

# The actual check
generate_and_check(target_obj, schema_obj)

def test_constant_array(self):
# First sanity check what we're setting up
schema_obj = {"const": [1, 2, 3]}
target_obj = [1, 2, 3]
validate(instance=target_obj, schema=schema_obj)

# The actual check
generate_and_check(target_obj, schema_obj)

def test_constant_object(self):
# First sanity check what we're setting up
schema_obj = {"const": {"a": 1, "b": 2}}
target_obj = {"a": 1, "b": 2}
validate(instance=target_obj, schema=schema_obj)

# The actual check
generate_and_check(target_obj, schema_obj)

def test_nested_constant(self):
# First sanity check what we're setting up
schema_obj = {"type": "object", "properties": {"a": {"const": 1}}}
target_obj = {"a": 1}
validate(instance=target_obj, schema=schema_obj)

# The actual check
generate_and_check(target_obj, schema_obj)

def test_constant_precedence(self):
schema_obj = {"type": "integer", "const": 1}
bad_string = _to_compact_json(2)

check_match_failure(
bad_string=bad_string,
good_bytes=b"",
failure_byte=b"2",
allowed_bytes={Byte(b"1")},
schema_obj=schema_obj,
)


class TestAdditionalProperties:

simple_schema = """{
Expand Down

0 comments on commit 14862a1

Please sign in to comment.