Open danmash opened 4 months ago
If you want only true but it's still a bool in the schema you can use default or const not enum
@ghandic none of these seems to work
In [20]: parameters_schema = {
...: "type": "object",
...: "friendly_name": "Corporate Structure Changes",
...: "description": "Parameters for corporate structure changes",
...: "properties": {
...: "new_parent": {"type": "boolean", "default": True},
...: "new_subsidiary": {"type": "boolean", "default": True},
...: "new_sibling": {"type": "boolean", "default": True},
...: },
...: }
In [21]: JSF(parameters_schema).generate()
Out[21]: {}
In [22]: JSF(parameters_schema).generate()
Out[22]: {'new_subsidiary': False}
In [23]: JSF(parameters_schema).generate()
Out[23]: {'new_subsidiary': True, 'new_sibling': False}
In [24]: parameters_schema = {
...: "type": "object",
...: "friendly_name": "Corporate Structure Changes",
...: "description": "Parameters for corporate structure changes",
...: "properties": {
...: "new_parent": {"type": "boolean", "const": True},
...: "new_subsidiary": {"type": "boolean", "const": True},
...: "new_sibling": {"type": "boolean", "const": True},
...: },
...: }
In [25]: JSF(parameters_schema).generate()
Out[25]: {'new_subsidiary': 1, 'new_sibling': 1}
Could you try adding required?
@ghandic these properties should not be required, my goal is to use "anyOf" to make sure at least one of the properties exists with "True" value.
In [26]: parameters_schema = {
...: "type": "object",
...: "friendly_name": "Corporate Structure Changes",
...: "description": "Parameters for corporate structure changes",
...: "properties": {
...: "new_parent": {"type": "boolean"},
...: "new_subsidiary": {"type": "boolean"},
...: "new_sibling": {"type": "boolean"},
...: },
...: "anyOf": [
...: {"properties": {"new_parent": {"const": True}}},
...: {"properties": {"new_subsidiary": {"const": True}}},
...: {"properties": {"new_sibling": {"const": True}}},
...: ]
...: }
In [27]: JSF(parameters_schema).generate()
Out[27]: {'new_subsidiary': True}
In [28]: JSF(parameters_schema).generate()
Out[28]: {'new_subsidiary': False}
I think what you're wanting would be
from jsf import JSF
parameters_schema = {
"type": "object",
"friendly_name": "Corporate Structure Changes",
"description": "Parameters for corporate structure changes",
"properties": {
"new_parent": {"type": "boolean", "default": True},
"new_subsidiary": {"type": "boolean", "default": True},
"new_sibling": {"type": "boolean", "default": True},
},
"minProperties": 1,
}
for _ in range(5):
print(JSF(parameters_schema).generate(use_defaults=True))
But we don't currently support minProperties, but this ensures only true values are set but not that at least one is set.
@ghandic Thank you for the proposed solution which is actually generated that I need. The only problem with using default
I see that it removes the opposite operation - validation of JSON based on the JSON schema.
In our project we use JSON schema for validation and I use JSF in our unit tests to randomly generate data for tests. It's true that when I switch from "enum" to "default" I'm able to generate the JSON needed, but I'm loosing the validation aspect of the JSON schema.
Original JSON schema we use for validation:
parameters_schema = {
"type": "object",
"friendly_name": "Corporate Structure Changes",
"description": "Parameters for corporate structure changes",
"properties": {
"new_parent": {"type": "boolean"},
"new_subsidiary": {"type": "boolean"},
"new_sibling": {"type": "boolean"},
},
"anyOf": [
{"properties": {"new_parent": {"enum": [True]}}},
{"properties": {"new_subsidiary": {"enum": [True]}}},
{"properties": {"new_sibling": {"enum": [True]}}},
]
}
Sorry for the misleading issue description. I hope now my task is clear. Thank you!
You can use examples
from jsf import JSF
parameters_schema = {
"type": "object",
"friendly_name": "Corporate Structure Changes",
"description": "Parameters for corporate structure changes",
"properties": {
"new_parent": {"type": "boolean", "examples": [True]},
"new_subsidiary": {"type": "boolean", "examples": [True]},
"new_sibling": {"type": "boolean", "examples": [True]},
},
}
for _ in range(5):
print(JSF(parameters_schema).generate(use_examples=True))
@ghandic examples
still doesn't validate data like constant
+ minProperties
does
In [42]: parameters_schema = {
...: "type": "object",
...: "friendly_name": "Corporate Structure Changes",
...: "description": "Parameters for corporate structure changes",
...: "properties": {
...: "new_parent": {"type": "boolean", "examples": [True]},
...: "new_subsidiary": {"type": "boolean", "examples": [True]},
...: "new_sibling": {"type": "boolean", "examples": [True]},
...: },
...: }
In [43]: for _ in range(5):
...: print(JSF(parameters_schema).generate(use_examples=True))
...:
{'new_parent': True, 'new_subsidiary': True}
{'new_subsidiary': True}
{'new_parent': True, 'new_subsidiary': True}
{'new_parent': True, 'new_subsidiary': True}
{'new_subsidiary': True}
In [44]: import jsonschema
In [45]: jsonschema.validate({'new_parent': False, 'new_sibling': False}, parameters_schema)
In [47]:
In [56]: parameters_schema = {
...: "type": "object",
...: "friendly_name": "Corporate Structure Changes",
...: "description": "Parameters for corporate structure changes",
...: "properties": {
...: "new_parent": {"type": "boolean", "const": True},
...: "new_subsidiary": {"type": "boolean", "const": True},
...: "new_sibling": {"type": "boolean", "const": True},
...: },
...: "minProperties": 1,
...: }
In [57]: jsonschema.validate({'new_parent': False, 'new_sibling': False}, parameters_schema)
---------------------------------------------------------------------------
ValidationError Traceback (most recent call last)
Cell In[57], line 1
----> 1 jsonschema.validate({'new_parent': False, 'new_sibling': False}, parameters_schema)
File ~/.pyenv/versions/3.8.17/envs/zint-django/lib/python3.8/site-packages/jsonschema/validators.py:1332, in validate(instance, schema, cls, *args, **kwargs)
1330 error = exceptions.best_match(validator.iter_errors(instance))
1331 if error is not None:
-> 1332 raise error
ValidationError: True was expected
Failed validating 'const' in schema['properties']['new_sibling']:
{'const': True, 'type': 'boolean'}
On instance['new_sibling']:
False
Ahh so the type isnt bool, you want it True all the time and the problem being when you set "const": True
it converts to an int?
Could you have a squiz at the PR - see if that addresses your problem
Hi @ghandic , sorry for the long reply. I double-check with my team about what we are trying to achieve. I added changes to your branch https://github.com/ghandic/jsf/pull/115 Below is an example of data validation
schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"new_parent": {"type": "boolean"},
"new_subsidiary": {"type": "boolean"},
"new_sibling": {"type": "boolean"},
},
"additionalProperties": False,
"anyOf": [
{"properties": {"new_parent": {"const": True}}},
{"properties": {"new_subsidiary": {"const": True}}},
{"properties": {"new_sibling": {"const": True}}},
]
,
}
valid_data1 = {"new_parent": True, "new_sibling": False}
valid_data2 = {"new_subsidiary": True, "new_parent": False, "new_sibling": True}
invalid_data = {"new_parent": False, "new_subsidiary": False, "new_sibling": False}
for data in [valid_data1, valid_data2, invalid_data]:
try:
jsonschema.validate(data, schema)
print(f"{data} is valid")
except jsonschema.exceptions.ValidationError as e:
print(f"{data} is invalid: {e}")
as you can see third sample is invalid, but jsf still generates invalid data sometimes
In [6]: JSF(schema).generate()
Out[6]: {'new_subsidiary': False, 'new_sibling': False}
In [9]: JSF(schema).generate()
Out[9]: {}
In [12]: JSF(schema).generate()
Out[12]: {'new_sibling': False}
It would be nice to have "minProperties": 1
as well, to avoid having empty dict generation
That's what the required does in the anyof/allof/oneof
Min properties doesn't scale well as if you add another optional property it wouldn't work
@ghandic here's schema we need without minProperties
and with required
as you suggested
False is allowed, but at least one value should be True
parameters_schema = {
"type": "object",
"friendly_name": "Corporate Structure Changes",
"description": "Parameters for corporate structure changes",
"properties": {
"new_parent": {"type": "boolean"},
"new_subsidiary": {"type": "boolean"},
"new_sibling": {"type": "boolean"},
},
"anyOf": [
{"properties": {"new_parent": {"const": True}}, "required": ["new_parent"]},
{"properties": {"new_subsidiary": {"const": True}}, "required": ["new_subsidiary"]},
{"properties": {"new_sibling": {"const": True}}, "required": ["new_sibling"]},
]
}
and JSF generates data which cannot pass the validation.
In [65]: JSF(parameters_schema).generate()
Out[65]: {}
In [81]: JSF(parameters_schema).generate()
Out[81]: {'new_parent': False, 'new_subsidiary': False}
In [82]: jsonschema.validate({"new_parent": False, "new_subsidiary": False},parameters_schema)
---------------------------------------------------------------------------
ValidationError Traceback (most recent call last)
Cell In[82], line 1
----> 1 jsonschema.validate({"new_parent": False, "new_subsidiary": False},parameters_schema)
File ~/.pyenv/versions/3.8.17/envs/zint-django/lib/python3.8/site-packages/jsonschema/validators.py:1332, in validate(instance, schema, cls, *args, **kwargs)
1330 error = exceptions.best_match(validator.iter_errors(instance))
1331 if error is not None:
-> 1332 raise error
ValidationError: True was expected
Failed validating 'const' in schema[0]['properties']['new_parent']:
{'const': True}
On instance['new_parent']:
False
Hi, I'm trying to generate the following dict containing up to 3 items with
True
values:However, I don't see a correct JSON schema to make this done with JSF. When I try to use
anyOf
I could getFalse
. On the other hand, if I'm trying to useenum
JSF generates1
.jsf==0.8.0
, (withjsf==0.11.2
I get slightly different results, see comment)