Skip to content

Commit e65f99e

Browse files
committed
Started to work on a parser for json schema
1 parent 59aac8e commit e65f99e

File tree

3 files changed

+164
-1
lines changed

3 files changed

+164
-1
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
<dependency>
5050
<groupId>org.mongodb</groupId>
5151
<artifactId>bson</artifactId>
52-
<version>4.10.2</version>
52+
<version>4.11.1</version>
5353
<optional>true</optional>
5454
</dependency>
5555
<dependency>

src/main/java/org/javawebstack/abstractdata/schema/AbstractSchema.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.javawebstack.abstractdata.schema;
22

33
import org.javawebstack.abstractdata.AbstractElement;
4+
import org.javawebstack.abstractdata.AbstractObject;
45
import org.javawebstack.abstractdata.AbstractPath;
56

67
import java.util.List;
@@ -69,4 +70,8 @@ static OneOfSchema oneOf(AbstractSchema... schemas) {
6970
return new OneOfSchema(schemas);
7071
}
7172

73+
static AbstractSchema fromJsonSchema(AbstractObject schema) {
74+
return new JsonSchemaParser().parse(schema);
75+
}
76+
7277
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package org.javawebstack.abstractdata.schema;
2+
3+
import org.javawebstack.abstractdata.AbstractArray;
4+
import org.javawebstack.abstractdata.AbstractElement;
5+
import org.javawebstack.abstractdata.AbstractObject;
6+
7+
import java.util.Collections;
8+
import java.util.List;
9+
10+
/*
11+
{
12+
"$id": "1224",
13+
"$schema": "https://json-schema.org/draft/2020-12/schema",
14+
"title": "Person",
15+
"type": "object",
16+
"properties": {
17+
"name": {
18+
"type": "string"
19+
},
20+
"emails": {
21+
"type": "array"
22+
"items": {
23+
"type": "string"
24+
}
25+
},
26+
"age": {
27+
"type": "integer",
28+
"minimum": 0,
29+
"maximum": 120
30+
}
31+
},
32+
"required": [
33+
"name",
34+
"emails"
35+
]
36+
}
37+
*/
38+
39+
public class JsonSchemaParser {
40+
41+
public static void main(String[] args) {
42+
String schemaStr = "{\n" +
43+
" \"$id\": \"1224\",\n" +
44+
" \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n" +
45+
" \"title\": \"Person\",\n" +
46+
" \"type\": \"object\",\n" +
47+
" \"properties\": {\n" +
48+
" \"name\": {\n" +
49+
" \"type\": \"string\"\n" +
50+
" },\n" +
51+
" \"emails\": {\n" +
52+
" \"type\": \"array\"\n" +
53+
" \"minItems\": 1\n" +
54+
" \"items\": {\n" +
55+
" \"type\": \"string\"\n" +
56+
" }\n" +
57+
" },\n" +
58+
" \"age\": {\n" +
59+
" \"type\": \"integer\",\n" +
60+
" \"minimum\": 0,\n" +
61+
" \"maximum\": 120\n" +
62+
" }\n" +
63+
" },\n" +
64+
" \"required\": [\n" +
65+
" \"name\",\n" +
66+
" \"emails\"\n" +
67+
" ]\n" +
68+
"}";
69+
AbstractObject schemaObj = AbstractElement.fromJson(schemaStr).object();
70+
AbstractSchema schema = new JsonSchemaParser().parse(schemaObj);
71+
List<SchemaValidationError> errors = schema.validate(new AbstractObject()
72+
.set("name", "Maher")
73+
.set("emails", new AbstractArray())
74+
.set("age", 123)
75+
);
76+
System.out.println();
77+
78+
}
79+
80+
public AbstractSchema parse(AbstractObject schema) {
81+
if(schema.has("type")) {
82+
switch (schema.string("type")) {
83+
case "object": {
84+
return parseObject(schema);
85+
}
86+
case "array": {
87+
return parseArray(schema);
88+
}
89+
case "string": {
90+
return parseString(schema);
91+
}
92+
case "integer": {
93+
return parseInteger(schema);
94+
}
95+
default: {
96+
throw new UnsupportedOperationException("Unknown type: " + schema.string("type"));
97+
}
98+
}
99+
}
100+
if(schema.has("$ref")) {
101+
throw new UnsupportedOperationException("$ref is currently not supported");
102+
}
103+
throw new IllegalArgumentException("Invalid json schema");
104+
}
105+
106+
private AbstractStringSchema parseString(AbstractObject schema) {
107+
if(!schema.string("type").equals("string"))
108+
throw new IllegalArgumentException("Not a valid string schema");
109+
AbstractStringSchema s = new AbstractStringSchema();
110+
111+
return s;
112+
}
113+
114+
private AbstractNumberSchema parseInteger(AbstractObject schema) {
115+
if(!schema.string("type").equals("integer"))
116+
throw new IllegalArgumentException("Not a valid integer schema");
117+
AbstractNumberSchema s = new AbstractNumberSchema();
118+
if(schema.has("minimum"))
119+
s.min(schema.number("minimum"));
120+
if(schema.has("maximum"))
121+
s.max(schema.number("maximum"));
122+
return s;
123+
}
124+
125+
private AbstractObjectSchema parseObject(AbstractObject schema) {
126+
if(!schema.string("type").equals("object"))
127+
throw new IllegalArgumentException("Not a valid object schema");
128+
AbstractObjectSchema s = new AbstractObjectSchema();
129+
List<String> required = schema.has("required") ? schema.array("required").toStringList() : Collections.emptyList();
130+
if(schema.has("properties")) {
131+
schema.object("properties").forEach((key, propSchema) -> {
132+
if(required.contains(key)) {
133+
s.requiredProperty(key, parse(propSchema.object()));
134+
} else {
135+
s.optionalProperty(key, parse(propSchema.object()));
136+
}
137+
});
138+
}
139+
return s;
140+
}
141+
142+
private AbstractArraySchema parseArray(AbstractObject schema) {
143+
if(!schema.string("type").equals("array"))
144+
throw new IllegalArgumentException("Not a valid array schema");
145+
AbstractArraySchema s = new AbstractArraySchema();
146+
if(schema.has("items")) {
147+
s.itemSchema(parse(schema.object("items")));
148+
}
149+
if(schema.has("minItems")) {
150+
s.min(schema.number("minItems").intValue());
151+
}
152+
if(schema.has("maxItems")) {
153+
s.max(schema.number("maxItems").intValue());
154+
}
155+
return s;
156+
}
157+
158+
}

0 commit comments

Comments
 (0)