Skip to content

Commit c8bfc83

Browse files
authored
Improve performance and fixes (#1086)
* Improve performance * Fix resolve
1 parent 60d034e commit c8bfc83

File tree

5 files changed

+79
-22
lines changed

5 files changed

+79
-22
lines changed

src/main/java/com/networknt/schema/JsonMetaSchema.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -439,11 +439,8 @@ public String readDynamicAnchor(JsonNode schemaNode) {
439439
}
440440

441441
private static String readText(JsonNode node, String field) {
442-
JsonNode idNode = node.get(field);
443-
if (idNode == null || !idNode.isTextual()) {
444-
return null;
445-
}
446-
return idNode.textValue();
442+
JsonNode fieldNode = node.get(field);
443+
return fieldNode == null ? null : fieldNode.textValue();
447444
}
448445

449446
public String getIri() {

src/main/java/com/networknt/schema/JsonNodePath.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public class JsonNodePath implements Comparable<JsonNodePath> {
2828
private final int pathSegmentIndex;
2929

3030
private volatile String value = null; // computed lazily
31+
private int hash = 0; // computed lazily
3132

3233
public JsonNodePath(PathType type) {
3334
this.type = type;
@@ -215,7 +216,12 @@ public String toString() {
215216

216217
@Override
217218
public int hashCode() {
218-
return Objects.hash(parent, pathSegment, pathSegmentIndex, type);
219+
int h = hash;
220+
if (h == 0) {
221+
h = Objects.hash(parent, pathSegment, pathSegmentIndex, type);
222+
hash = h;
223+
}
224+
return h;
219225
}
220226

221227
@Override

src/main/java/com/networknt/schema/JsonSchema.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ public class JsonSchema extends BaseJsonValidator {
6565
static JsonSchema from(ValidationContext validationContext, SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parent, boolean suppressSubSchemaRetrieval) {
6666
return new JsonSchema(validationContext, schemaLocation, evaluationPath, schemaNode, parent, suppressSubSchemaRetrieval);
6767
}
68-
68+
6969
private boolean hasNoFragment(SchemaLocation schemaLocation) {
70-
return this.schemaLocation.getFragment() == null || this.schemaLocation.getFragment().getNameCount() == 0;
70+
JsonNodePath fragment = this.schemaLocation.getFragment();
71+
return fragment == null || (fragment.getParent() == null && fragment.getNameCount() == 0);
7172
}
72-
73+
7374
private static SchemaLocation resolve(SchemaLocation schemaLocation, JsonNode schemaNode, boolean rootSchema,
7475
ValidationContext validationContext) {
7576
String id = validationContext.resolveSchemaId(schemaNode);
@@ -112,7 +113,7 @@ private JsonSchema(ValidationContext validationContext, SchemaLocation schemaLoc
112113
if (id != null) {
113114
// In earlier drafts $id may contain an anchor fragment see draft4/idRef.json
114115
// Note that json pointer fragments in $id are not allowed
115-
SchemaLocation result = id.contains("#") ? schemaLocation.resolve(id) : this.schemaLocation;
116+
SchemaLocation result = id.indexOf('#') != -1 ? schemaLocation.resolve(id) : this.schemaLocation;
116117
if (hasNoFragment(result)) {
117118
this.id = id;
118119
} else {

src/main/java/com/networknt/schema/SchemaLocation.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,24 @@ public SchemaLocation resolve(String absoluteIriReferenceOrFragment) {
142142
return new SchemaLocation(this.getAbsoluteIri(), JSON_POINTER);
143143
}
144144
JsonNodePath fragment = JSON_POINTER;
145-
String[] parts = absoluteIriReferenceOrFragment.split("#");
145+
int index = absoluteIriReferenceOrFragment.indexOf('#');
146146
AbsoluteIri absoluteIri = this.getAbsoluteIri();
147+
String part0 = index == -1 ? absoluteIriReferenceOrFragment
148+
: absoluteIriReferenceOrFragment.substring(0, index);
147149
if (absoluteIri != null) {
148-
if (!parts[0].isEmpty()) {
149-
absoluteIri = absoluteIri.resolve(parts[0]);
150+
if (!part0.isEmpty()) {
151+
absoluteIri = absoluteIri.resolve(part0);
150152
}
151153
} else {
152-
absoluteIri = AbsoluteIri.of(parts[0]);
154+
absoluteIri = AbsoluteIri.of(part0);
153155
}
154-
if (parts.length > 1 && !parts[1].isEmpty()) {
155-
fragment = Fragment.of(parts[1]);
156+
if (index != -1) {
157+
if (absoluteIriReferenceOrFragment.length() > index + 1) {
158+
String part1 = absoluteIriReferenceOrFragment.substring(index + 1);
159+
if (!part1.isEmpty()) {
160+
fragment = Fragment.of(part1);
161+
}
162+
}
156163
}
157164
return new SchemaLocation(absoluteIri, fragment);
158165
}
@@ -168,18 +175,26 @@ public static String resolve(SchemaLocation schemaLocation, String absoluteIriRe
168175
if ("#".equals(absoluteIriReferenceOrFragment)) {
169176
return schemaLocation.getAbsoluteIri().toString() + "#";
170177
}
171-
String[] parts = absoluteIriReferenceOrFragment.split("#");
178+
int index = absoluteIriReferenceOrFragment.indexOf('#');
172179
AbsoluteIri absoluteIri = schemaLocation.getAbsoluteIri();
173-
String resolved = parts[0];
180+
String part0 = index == -1 ? absoluteIriReferenceOrFragment
181+
: absoluteIriReferenceOrFragment.substring(0, index);
182+
String resolved = part0;
174183
if (absoluteIri != null) {
175-
if (!parts[0].isEmpty()) {
176-
resolved = absoluteIri.resolve(parts[0]).toString();
184+
if (!part0.isEmpty()) {
185+
resolved = absoluteIri.resolve(part0).toString();
177186
} else {
178187
resolved = absoluteIri.toString();
179188
}
180189
}
181-
if (parts.length > 1 && !parts[1].isEmpty()) {
182-
resolved = resolved + "#" + parts[1];
190+
String part1 = "";
191+
if (index != -1) {
192+
if (absoluteIriReferenceOrFragment.length() > index + 1) {
193+
part1 = absoluteIriReferenceOrFragment.substring(index + 1);
194+
}
195+
}
196+
if (!part1.isEmpty()) {
197+
resolved = resolved + "#" + part1;
183198
} else {
184199
resolved = resolved + "#";
185200
}

src/test/java/com/networknt/schema/SchemaLocationTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ void schemaLocationResolveDocumentPointer() {
7474
SchemaLocation.resolve(schemaLocation, "#/allOf/12/properties"));
7575
}
7676

77+
@Test
78+
void schemaLocationResolveHashInFragment() {
79+
SchemaLocation schemaLocation = SchemaLocation.of("https://example.com/schemas/address#street_address");
80+
assertEquals(
81+
"https://example.com/schemas/address#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema",
82+
SchemaLocation.resolve(schemaLocation,
83+
"#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema"));
84+
}
85+
86+
@Test
87+
void schemaLocationResolvePathHashInFragment() {
88+
SchemaLocation schemaLocation = SchemaLocation.of("https://example.com/schemas/address#street_address");
89+
assertEquals(
90+
"https://example.com/schemas/hello#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema",
91+
SchemaLocation.resolve(schemaLocation,
92+
"hello#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema"));
93+
}
94+
7795
@Test
7896
void schemaLocationResolveEmptyString() {
7997
SchemaLocation schemaLocation = SchemaLocation.of("https://example.com/schemas/address#street_address");
@@ -105,6 +123,26 @@ void resolveDocumentPointer() {
105123
schemaLocation.resolve("#/allOf/10/properties").toString());
106124
}
107125

126+
@Test
127+
void resolveHashInFragment() {
128+
SchemaLocation schemaLocation = SchemaLocation.of("https://example.com/schemas/address#street_address");
129+
assertEquals(
130+
"https://example.com/schemas/address#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema",
131+
schemaLocation.resolve(
132+
"#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema")
133+
.toString());
134+
}
135+
136+
@Test
137+
void resolvePathHashInFragment() {
138+
SchemaLocation schemaLocation = SchemaLocation.of("https://example.com/schemas/address#street_address");
139+
assertEquals(
140+
"https://example.com/schemas/hello#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema",
141+
schemaLocation.resolve(
142+
"hello#/paths/~1subscribe/post/callbacks/myEvent/{request.body#~1callbackUrl}/post/requestBody/content/application~1json/schema")
143+
.toString());
144+
}
145+
108146
@Test
109147
void resolveEmptyString() {
110148
SchemaLocation schemaLocation = SchemaLocation.of("https://example.com/schemas/address#street_address");

0 commit comments

Comments
 (0)