erosb / json-skema Goto Github PK
View Code? Open in Web Editor NEWJSON Schema Validator for the JVM, implements draft2020-12
License: MIT License
JSON Schema Validator for the JVM, implements draft2020-12
License: MIT License
Hello, your work is very good and has solved many of my problems, especially for error reports, I haven't found a good way to handle them from other jsonschema projects。I hope you can support the tuple mode of array.items. Thank you very much。
Input some json below, it throw error.
json code:
{ "type": "array", "title": "array desc", "items": [ {"type": "object", "title": "some obj"} ] }
cause
Caused by: kotlin.NotImplementedError: An operation is not implemented. at com.github.erosb.jsonsKema.SchemaLoader.doLoadSchema(SchemaLoader.kt:428) at com.github.erosb.jsonsKema.SchemaLoader.loadChild$json_sKema(SchemaLoader.kt:515) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1$1$ctx$1.invoke(SchemaLoader.kt:452) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1$1$ctx$1.invoke(SchemaLoader.kt:450) at com.github.erosb.jsonsKema.ItemsKt$itemsSchemaLoader$1.invoke(Items.kt:10) at com.github.erosb.jsonsKema.ItemsKt$itemsSchemaLoader$1.invoke(Items.kt:8) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1.invoke(SchemaLoader.kt:475) at com.github.erosb.jsonsKema.SchemaLoader$createCompositeSchema$1.invoke(SchemaLoader.kt:447) at com.github.erosb.jsonsKema.SchemaLoader.enterScope(SchemaLoader.kt:176) at com.github.erosb.jsonsKema.SchemaLoader.createCompositeSchema(SchemaLoader.kt:447)
Hey @erosb,
I find it generally very useful to make use of GitHub's Dependabot to keep all your project's dependencies up to date. I know this project doesn't have much in the way of release dependencies, but it can't hurt to automate it.
Happy to help if you want.
Hi,
I've recently needed to compare the performance and functionality of this and other JVM based JSON validation libraries, and I thought you might like to see how this implementation compares. I've published to the code and the results here: https://github.com/creek-service/json-schema-validation-comparison.
While I've spent time trying to get the best out of each library under test, it's possible that the results for this implementation could be improved if someone with more in-depth knowledge were to look into it. If you feel I'm not showing in its best light, please feel free to raise PRs to fix issues and improve your score.
Please feel free to link to the code and results.
I hope this is of some use to you.
Thanks,
Andy
Hello,
I am receiving for one event validation following error
kotlin.NotImplementedError: An operation is not implemented: something went wrong: com.github.erosb.jsonsKema.MarkableJsonObject@13b61e54 vs {
"feature": "some-val",
"element": "some-val",
"action": "some-val"
}
at com.github.erosb.jsonsKema.AggregatingValidationFailure.join$json_sKema(ValidationFailure.kt:67) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.accumulate(Validator.kt:711) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.accumulate(Validator.kt:156) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.SchemaVisitor.visitCompositeSchema(SchemaVisitor.kt:71) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.access$visitCompositeSchema$s680550253(Validator.kt:156) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator$visitCompositeSchema$2.invoke(Validator.kt:259) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator$visitCompositeSchema$2.invoke(Validator.kt:258) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.withOtherInstance(Validator.kt:352) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.visitCompositeSchema(Validator.kt:258) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.visitCompositeSchema(Validator.kt:156) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.SchemaVisitor.internallyVisitCompositeSchema$json_sKema(SchemaVisitor.kt:55) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.CompositeSchema.accept(Schema.kt:26) ~[json-sKema-0.13.0.jar:na]
at com.github.erosb.jsonsKema.DefaultValidator.validate(Validator.kt:249) ~[json-sKema-0.13.0.jar:na]
at com.bonial.tracking.trackingpolicing.service.SchemaValidator.validate(SchemaValidator.java:79) ~[classes/:na]
--> rest i cutted
Tried to debug through the code and I relly cant find the issue.
Using Java 11, json sKema 0.13.0 and also set the kotlin version to 1.9 in my pom.
Is there anything I can do?
Implementers guide https://bowtie-json-schema.readthedocs.io/en/latest/implementers/
Hello , I am exploring json-sKema library for schema validation.
I have below schema , how can i resolve city and state json schema during validation.
On validating schema with below data, i expect it to fail validation. But it pass the validation
"{"firstName":"ABC","lastName":"ABC","age":20,"city":{"city1":{"name":20,"zipCode":"45676"}}}\n"
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "The citizen's first name."
},
"lastName": {
"type": "string",
"description": "The citizen's last name."
},
"age": {
"description": "Age in years which must be equal to or greater than zero.",
"type": "integer",
"minimum": 0
},
"city": {
"type": "object",
"properties": {
"city1": { "$ref": "city.json"},
"state": {"$ref": "state.json"}
}
}
}
}
city.json {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The city's name."
},
"zipCode": {
"type": "integer",
"description": "The zip code.",
"minimum": 0
}
}
}
state.json {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The city's name."
},
"zipCode": {
"type": "integer",
"description": "The zip code.",
"minimum": 0
}
}
}
In Readme:
// create a validator instance for each validation (one-time use object)
Validator validator = Validator.create(schema, new ValidatorConfig(FormatValidationPolicy.ALWAYS));
But in version 0.12.0:
new ValidatorConfig(FormatValidationPolicy.ALWAYS)
doesn't exists.
Hello,
It would be very useful if a SchemaException (or similar) would be thrown when loading a Schema with errors (such as invalid references, or wrongly used keywords). At the moment, an Error is thrown, which is too generic and also does not provide a JSON pointer (like the previous library).
Thank you for your great work!
Regards,
Florin
Create a schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Timestamp Test",
"type": "object",
"properties": {
"@timestamp": {
"description": "The UTC date and time the event was created",
"type": "string",
"format": "date-time"
}
}
}
Create three test JSON files:
{
"@timestamp": "2023-07-06T20:20:10.388-02:00"
}
{
"@timestamp": "2023-07-06T20:20:10.388Z"
}
{
"@timestamp": "2023-07-06T20:20:10.388"
}
The first two will validate against the schema, the third one does not.
The standard ISO 8601 date/time specification makes the timezone specification optional. Other JSON Schema libraries handle this correctly (e.g., "check-jsonschema").
Hi
Thanks for providing this library. I am looking to use it in my projects. The "About" section of the library says "(under development)". I am assuming there are some features of 2020-12 which are missing in it right now.
Is there a list detailing supported and unsupported features? Such a list will help in tracking progress and help contributors effectively contribute to this library.
Hello,
I have a problem when working with multiple schemas which refer to the internal content.
NOTE: The test cases below are based on RefResolutionTest.kt class.
When working with a root schema referencing its internal variables, the properties are resolved successfully, for instance:
@Test
fun `ref definitions`() {
val root: CompositeSchema = createSchemaLoaderForString(
"""
{
"$ref": "#/$defs/ddd",
"$defs": {
"ddd": {
"title": "my title",
"$anchor": "myAnchor"
}
}
}
""".trimIndent()
)() as CompositeSchema
val actual = root.accept(TraversingSchemaVisitor<String>("$ref", "title"))!!
assertThat(actual).isEqualTo("my title")
}
Here we refer to "ddd" header directly from the schema and it works well, returning the correct value.
If we want to add a simple subSchema and refer it from the root schema, it works well as well:
@Test
fun `ref definitions child`() {
val actual = createSchemaLoaderForString(
"""
{
"$ref": "http://subschema.json#/$defs/ddd"
}
""",
mapOf(
Pair(
"http://subschema.json",
"""
{
"$defs": {
"ddd": {
"title": "my title",
"$anchor": "myAnchor"
}
}
}
"""
)
)
)() as CompositeSchema
val referred = (actual.subschemas.iterator().next() as ReferenceSchema).referredSchema as CompositeSchema
assertThat(referred.title!!.value).isEqualTo("my title")
}
However, if the subSchema uses internal "$ref" reference, that fails as the application is looking for the referenced object in the root schema, and not within the subSchema.
For instance, if we move the schema from the first example to a be a subschema in the second example, it does not longer work:
@Test
fun `ref definitions child self ref`() {
val actual = createSchemaLoaderForString(
"""
{
"$ref": "http://subschema.json#/$defs/ddd"
}
""",
mapOf(
Pair(
"http://subschema.json",
"""
{
"$ref": "#/$defs/ddd",
"$defs": {
"ddd": {
"title": "my title",
"$anchor": "myAnchor"
}
}
}
"""
)
)
)() as CompositeSchema
}
and returns the following error:
java.lang.Error: json pointer evaluation error: could not resolve property $defs in {
"$ref": "http://subschema.json#/$defs/ddd"
}
at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$lookupNext$1.invoke(SchemaLoader.kt:375)
at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$lookupNext$1.invoke(SchemaLoader.kt:366)
at com.github.erosb.jsonsKema.SchemaLoader.enterScope(SchemaLoader.kt:176)
at com.github.erosb.jsonsKema.SchemaLoader.evaluateJsonPointer$lookupNext(SchemaLoader.kt:366)
at com.github.erosb.jsonsKema.SchemaLoader.access$evaluateJsonPointer$lookupNext(SchemaLoader.kt:107)
at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$1.invoke(SchemaLoader.kt:404)
at com.github.erosb.jsonsKema.SchemaLoader$evaluateJsonPointer$1.invoke(SchemaLoader.kt:403)
at com.github.erosb.jsonsKema.SchemaLoader.runWithChangedBaseURI(SchemaLoader.kt:412)
at com.github.erosb.jsonsKema.SchemaLoader.evaluateJsonPointer(SchemaLoader.kt:403)
at com.github.erosb.jsonsKema.SchemaLoader.resolve(SchemaLoader.kt:353)
at com.github.erosb.jsonsKema.SchemaLoader.loadSchema(SchemaLoader.kt:305)
at com.github.erosb.jsonsKema.SchemaLoader.loadRootSchema(SchemaLoader.kt:290)
at com.github.erosb.jsonsKema.SchemaLoader.invoke(SchemaLoader.kt:184)
So it looks like it tries to resolve the "ddd" header from the root schema, when it is defined within the subSchema itself.
Would it be possible to fix the issue as it blocks our project from upgrading from everit library?
Thank you!
Best regards,
Aleksandr.
Hi,
I am trying to validate against a schema that does not allow unevaluated properties and I'm getting the following error every single time: false schema always fails
. I managed to reproduce the behavior on a smaller schema:
Schema: { "$schema": "http://json-schema.org/draft/2020-12/schema#", "type": "object", "properties": { "key2": { "type": "string" } }, "unevaluatedProperties": false }
Document to validate: { "key": "val" }
Any thoughts on this?
Thanks in advance,
Florin
Hi, is this option of readOnly/writeOnly context validation somehow lost in json-skema?
https://github.com/everit-org/json-schema#readonly-and-writeonly-context
Is it possible to write our own schemas to extend the current definitions? For an example, there is a https://json-schema-faker.js.org/ project that allows users to define "faker" value for their properties. An example of such schema is:
{
"type": "object",
"properties": {
"name": {
"type": "string",
"faker": "name.findName"
},
"email": {
"type": "string",
"faker": "internet.email"
}
},
"required": [
"name",
"email"
]
}
json-sKema will parse all properties except "faker" since it is not a registered keyword. I would like to write my own FakerSchema
and extend the SchemaVisitor
to allow visiting the new schemas.
Is something like this possible with the library?
Hi @erosb ,
While using this library against our test suite, I ran into a validation error on a complex schema. Below is the code that returns the error.
package io.confluent.kafka.schemaregistry.json.schema;
import com.github.erosb.jsonsKema.IJsonValue;
import com.github.erosb.jsonsKema.JsonParseException;
import com.github.erosb.jsonsKema.JsonParser;
import com.github.erosb.jsonsKema.JsonValue;
import com.github.erosb.jsonsKema.Schema;
import com.github.erosb.jsonsKema.SchemaClient;
import com.github.erosb.jsonsKema.SchemaLoader;
import com.github.erosb.jsonsKema.SchemaLoaderConfig;
import com.github.erosb.jsonsKema.SchemaLoadingException;
import com.github.erosb.jsonsKema.Validator;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.Test;
public class ReferenceTest {
private static final String DUMMY_BASE_URI = "dummy://input/";
@Test
public void testReferences() throws Exception {
String doc = "{\n"
+ " \"customerName\": \"acme\",\n"
+ " \"acquireDate\": \"2020-12-12\"\n"
+ "}";
JsonValue jsonValue = new JsonParser(doc).parse();
String oneOfSchema = "{\n"
+ " \"oneOf\": [\n"
+ " { \"$ref\": \"customer.json\"},\n"
+ " { \"$ref\": \"user.json\"}\n"
+ " ]\n"
+ "}";
String userSchema = "{\n"
+ " \"type\": \"object\",\n"
+ " \"additionalProperties\": false,\n"
+ " \"properties\": {\n"
+ " \"name\": {\n"
+ " \"type\": \"string\"\n"
+ " },\n"
+ " \"age\": {\n"
+ " \"type\": \"integer\",\n"
+ " \"minimum\": 0\n"
+ " }\n"
+ " },\n"
+ " \"required\": [\n"
+ " \"age\"\n"
+ " ]\n"
+ "}\n";
String customerSchema = "{\n"
+ " \"type\": \"object\",\n"
+ " \"additionalProperties\": false,\n"
+ " \"properties\": {\n"
+ " \"customerName\": {\n"
+ " \"type\": \"string\"\n"
+ " },\n"
+ " \"acquireDate\": {\n"
+ " \"type\": \"string\"\n"
+ " }\n"
+ " }\n"
+ "}\n";
Map<URI, String> refs = new HashMap<>();
refs.put(new URI(DUMMY_BASE_URI + "user.json"), userSchema);
refs.put(new URI(DUMMY_BASE_URI + "customer.json"), customerSchema);
SchemaLoaderConfig config = new SchemaLoaderConfig(
new ReferenceSchemaClient(refs), DUMMY_BASE_URI);
JsonValue schemaJson = new JsonParser(oneOfSchema).parse();
Schema loadedSchema = new SchemaLoader(schemaJson, config).load();
Validator validator = Validator.forSchema(loadedSchema);
validator.validate(jsonValue);
}
public static class ReferenceSchemaClient implements SchemaClient {
private Map<URI, String> references;
public ReferenceSchemaClient(Map<URI, String> references) {
this.references = references;
}
@Override
public InputStream get(URI uri) {
String reference = references.get(uri);
if (reference == null) {
throw new UncheckedIOException(new FileNotFoundException(uri.toString()));
}
return new ByteArrayInputStream(reference.getBytes(StandardCharsets.UTF_8));
}
@Override
public IJsonValue getParsed(URI uri) {
BufferedReader reader = new BufferedReader(new InputStreamReader(get(uri)));
String string = reader.lines().collect(Collectors.joining());
try {
return new JsonParser(string, uri).parse();
} catch (JsonParseException ex) {
throw new SchemaLoadingException("failed to parse json content returned from $uri", ex);
}
}
}
}
Oddly, if I remove "required": ["age"]
from userSchema
, then the "something went wrong" error does not appear.
Java 17 support
Just browsing through the code, but it seems to me that in UnevaluatedProperties.kt, Keyword.UNEVALUATED_ITEMS should be Keyword.UNEVALUATED_PROPERTIES
When using this library, calls to the static method java.net.URLDecoder.decode(String, Charset)
force a minimum Android API level 33[1].
In order to allow using this library on earlier android api versions, code like the following should be replaced throughout the library:
-URLDecoder.decode(s, StandardCharsets.UTF_8)
+URLDecoder.decode(s, StandardCharsets.UTF_8.name())
Currently JsonTypingException only overrides the toString
method, whereas JsonParseException only overrides the message
field. Is this intentional?
I’m asking, because imho it makes processing these exceptions more difficult than necessary, because you need separate logic for retrieving the detail message: for JsonTypingException you have to call toString
, while for JsonParseException you have to access the message
field.
If it helps, I’d be happy to provide a PR.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.