Skip to content

Commit b65788e

Browse files
committed
GH-5723: migrate rdf4j-rio-rdfjson to Jackson 3.1.2
- Update jackson-core dependency to tools.jackson.core groupId - Replace JsonFactoryBuilder + removed INTERN/CANONICALIZE_FIELD_NAMES features with JsonFactory.builder() - JsonLocation renamed to TokenStreamLocation - ALLOW_UNQUOTED_FIELD_NAMES renamed to ALLOW_UNQUOTED_PROPERTY_NAMES - JsonParser API: getCurrentLocation/Name/Token → currentLocation/Name/Token - JsonGenerator API: writeObjectField/ArrayFieldStart → writeStringProperty/writeObjectPropertyStart/writeArrayPropertyStart - setPrettyPrinter() removed; replaced with ObjectWriteContext at generator creation time - modelToRdfJsonInternal: remove throws IOException and duplicate pretty-printer setup (now configured via ObjectWriteContext in startRDF) - Exception handling: IOException catches replaced with JacksonException - Test: JsonProcessingException → JacksonException, update ContentReference import
1 parent 67fe595 commit b65788e

4 files changed

Lines changed: 114 additions & 119 deletions

File tree

core/rio/rdfjson/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@
3333
<scope>runtime</scope>
3434
</dependency>
3535
<dependency>
36-
<groupId>com.fasterxml.jackson.core</groupId>
36+
<groupId>tools.jackson.core</groupId>
3737
<artifactId>jackson-core</artifactId>
38+
<version>${jackson3.version}</version>
3839
</dependency>
3940
<dependency>
4041
<groupId>commons-io</groupId>

core/rio/rdfjson/src/main/java/org/eclipse/rdf4j/rio/rdfjson/RDFJSONParser.java

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@
3232
import org.eclipse.rdf4j.rio.helpers.AbstractRDFParser;
3333
import org.eclipse.rdf4j.rio.helpers.JSONSettings;
3434

35-
import com.fasterxml.jackson.core.JsonFactory;
36-
import com.fasterxml.jackson.core.JsonFactoryBuilder;
37-
import com.fasterxml.jackson.core.JsonLocation;
38-
import com.fasterxml.jackson.core.JsonParseException;
39-
import com.fasterxml.jackson.core.JsonParser;
40-
import com.fasterxml.jackson.core.JsonToken;
41-
import com.fasterxml.jackson.core.StreamReadFeature;
42-
import com.fasterxml.jackson.core.StreamWriteFeature;
43-
import com.fasterxml.jackson.core.json.JsonReadFeature;
35+
import tools.jackson.core.JacksonException;
36+
import tools.jackson.core.JsonParser;
37+
import tools.jackson.core.JsonToken;
38+
import tools.jackson.core.StreamReadFeature;
39+
import tools.jackson.core.StreamWriteFeature;
40+
import tools.jackson.core.TokenStreamFactory;
41+
import tools.jackson.core.TokenStreamLocation;
42+
import tools.jackson.core.json.JsonFactory;
43+
import tools.jackson.core.json.JsonReadFeature;
4444

4545
/**
4646
* {@link RDFParser} implementation for the RDF/JSON format
@@ -86,9 +86,9 @@ public void parse(final InputStream inputStream, final String baseUri)
8686

8787
jp = configureNewJsonFactory().createParser(inputStream);
8888
rdfJsonToHandlerInternal(this.rdfHandler, this.valueFactory, jp);
89-
} catch (final IOException e) {
89+
} catch (JacksonException e) {
9090
if (jp != null) {
91-
reportFatalError("Found IOException during parsing", e, jp.getCurrentLocation());
91+
reportFatalError("Found IOException during parsing", e, jp.currentLocation());
9292
} else {
9393
reportFatalError(e);
9494
}
@@ -97,8 +97,8 @@ public void parse(final InputStream inputStream, final String baseUri)
9797
if (jp != null) {
9898
try {
9999
jp.close();
100-
} catch (final IOException e) {
101-
reportFatalError("Found exception while closing JSON parser", e, jp.getCurrentLocation());
100+
} catch (final JacksonException e) {
101+
reportFatalError("Found exception while closing JSON parser", e, jp.currentLocation());
102102
}
103103
}
104104
}
@@ -109,36 +109,36 @@ public void parse(final InputStream inputStream, final String baseUri)
109109

110110
/**
111111
* Creates a literal, using the current value, language, and datatype, and additionally using the given
112-
* {@link JsonLocation} to provide information about the line and column numbers in the event of a warning, error or
113-
* exception being generated by the creation of the literal.
112+
* {@link TokenStreamLocation} to provide information about the line and column numbers in the event of a warning,
113+
* error or exception being generated by the creation of the literal.
114114
*
115115
* @param label the literal's lexical label
116116
* @param language the literal's language tag. Can be null.
117117
* @param datatype the literal's datatype. Can be null.
118-
* @param currentLocation the current JsonLocation. May not be null.
118+
* @param currentLocation the current TokenStreamLocation. May not be null.
119119
* @return the created {@link Literal} object.
120120
* @throws RDFParseException
121121
*/
122-
protected Literal createLiteral(String label, String language, IRI datatype, JsonLocation currentLocation)
122+
protected Literal createLiteral(String label, String language, IRI datatype, TokenStreamLocation currentLocation)
123123
throws RDFParseException {
124124
return createLiteral(label, language, datatype, currentLocation.getLineNr(), currentLocation.getColumnNr());
125125
}
126126

127-
protected void reportError(String msg, Exception e, JsonLocation location, RioSetting<Boolean> setting)
127+
protected void reportError(String msg, Exception e, TokenStreamLocation location, RioSetting<Boolean> setting)
128128
throws RDFParseException {
129129
reportError(msg, e, location.getLineNr(), location.getColumnNr(), setting);
130130
}
131131

132-
protected void reportError(String msg, JsonLocation location, RioSetting<Boolean> setting)
132+
protected void reportError(String msg, TokenStreamLocation location, RioSetting<Boolean> setting)
133133
throws RDFParseException {
134134
reportError(msg, location.getLineNr(), location.getColumnNr(), setting);
135135
}
136136

137-
protected void reportFatalError(String msg, Exception e, JsonLocation location) throws RDFParseException {
137+
protected void reportFatalError(String msg, Exception e, TokenStreamLocation location) throws RDFParseException {
138138
reportFatalError(msg, e, location.getLineNr(), location.getColumnNr());
139139
}
140140

141-
protected void reportFatalError(String msg, JsonLocation location) throws RDFParseException {
141+
protected void reportFatalError(String msg, TokenStreamLocation location) throws RDFParseException {
142142
reportFatalError(msg, location.getLineNr(), location.getColumnNr());
143143
}
144144

@@ -156,9 +156,9 @@ public void parse(final Reader reader, final String baseUri)
156156

157157
jp = configureNewJsonFactory().createParser(reader);
158158
rdfJsonToHandlerInternal(rdfHandler, valueFactory, jp);
159-
} catch (final IOException e) {
159+
} catch (JacksonException e) {
160160
if (jp != null) {
161-
reportFatalError("Found IOException during parsing", e, jp.getCurrentLocation());
161+
reportFatalError("Found IOException during parsing", e, jp.currentLocation());
162162
} else {
163163
reportFatalError(e);
164164
}
@@ -167,8 +167,8 @@ public void parse(final Reader reader, final String baseUri)
167167
if (jp != null) {
168168
try {
169169
jp.close();
170-
} catch (final IOException e) {
171-
reportFatalError("Found exception while closing JSON parser", e, jp.getCurrentLocation());
170+
} catch (final JacksonException e) {
171+
reportFatalError("Found exception while closing JSON parser", e, jp.currentLocation());
172172
}
173173
}
174174
}
@@ -178,37 +178,37 @@ public void parse(final Reader reader, final String baseUri)
178178
}
179179

180180
private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFactory vf, final JsonParser jp)
181-
throws IOException, JsonParseException, RDFParseException, RDFHandlerException {
181+
throws RDFParseException, RDFHandlerException {
182182
if (jp.nextToken() != JsonToken.START_OBJECT) {
183-
reportFatalError("Expected RDF/JSON document to start with an Object", jp.getCurrentLocation());
183+
reportFatalError("Expected RDF/JSON document to start with an Object", jp.currentLocation());
184184
}
185185

186186
while (jp.nextToken() != JsonToken.END_OBJECT) {
187-
final String subjStr = jp.getCurrentName();
187+
final String subjStr = jp.currentName();
188188
Resource subject;
189189

190190
subject = subjStr.startsWith("_:") ? createNode(subjStr.substring(2)) : vf.createIRI(subjStr);
191191
if (jp.nextToken() != JsonToken.START_OBJECT) {
192-
reportFatalError("Expected subject value to start with an Object", jp.getCurrentLocation());
192+
reportFatalError("Expected subject value to start with an Object", jp.currentLocation());
193193
}
194194

195195
boolean foundPredicate = false;
196196
while (jp.nextToken() != JsonToken.END_OBJECT) {
197-
final String predStr = jp.getCurrentName();
197+
final String predStr = jp.currentName();
198198

199199
final IRI predicate = vf.createIRI(predStr);
200200
foundPredicate = true;
201201

202202
if (jp.nextToken() != JsonToken.START_ARRAY) {
203-
reportFatalError("Expected predicate value to start with an array", jp.getCurrentLocation());
203+
reportFatalError("Expected predicate value to start with an array", jp.currentLocation());
204204
}
205205

206206
boolean foundObject = false;
207207

208208
while (jp.nextToken() != JsonToken.END_ARRAY) {
209-
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
209+
if (jp.currentToken() != JsonToken.START_OBJECT) {
210210
reportFatalError("Expected object value to start with an Object: subject=<" + subjStr
211-
+ "> predicate=<" + predStr + ">", jp.getCurrentLocation());
211+
+ "> predicate=<" + predStr + ">", jp.currentLocation());
212212
}
213213

214214
String nextValue = null;
@@ -218,13 +218,13 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
218218
final Set<String> nextContexts = new HashSet<>(2);
219219

220220
while (jp.nextToken() != JsonToken.END_OBJECT) {
221-
final String fieldName = jp.getCurrentName();
221+
final String fieldName = jp.currentName();
222222
if (RDFJSONUtility.VALUE.equals(fieldName)) {
223223
if (nextValue != null) {
224224
reportError(
225225
"Multiple values found for a single object: subject=" + subjStr + " predicate="
226226
+ predStr,
227-
jp.getCurrentLocation(), RDFJSONParserSettings.FAIL_ON_MULTIPLE_OBJECT_VALUES);
227+
jp.currentLocation(), RDFJSONParserSettings.FAIL_ON_MULTIPLE_OBJECT_VALUES);
228228
}
229229

230230
jp.nextToken();
@@ -235,7 +235,7 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
235235
reportError(
236236
"Multiple types found for a single object: subject=" + subjStr + " predicate="
237237
+ predStr,
238-
jp.getCurrentLocation(), RDFJSONParserSettings.FAIL_ON_MULTIPLE_OBJECT_TYPES);
238+
jp.currentLocation(), RDFJSONParserSettings.FAIL_ON_MULTIPLE_OBJECT_TYPES);
239239
}
240240

241241
jp.nextToken();
@@ -246,7 +246,7 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
246246
reportError(
247247
"Multiple languages found for a single object: subject=" + subjStr
248248
+ " predicate=" + predStr,
249-
jp.getCurrentLocation(),
249+
jp.currentLocation(),
250250
RDFJSONParserSettings.FAIL_ON_MULTIPLE_OBJECT_LANGUAGES);
251251
}
252252

@@ -258,7 +258,7 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
258258
reportError(
259259
"Multiple datatypes found for a single object: subject=" + subjStr
260260
+ " predicate=" + predStr,
261-
jp.getCurrentLocation(),
261+
jp.currentLocation(),
262262
RDFJSONParserSettings.FAIL_ON_MULTIPLE_OBJECT_DATATYPES);
263263
}
264264

@@ -267,7 +267,7 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
267267
nextDatatype = jp.getText();
268268
} else if (RDFJSONUtility.GRAPHS.equals(fieldName)) {
269269
if (jp.nextToken() != JsonToken.START_ARRAY) {
270-
reportError("Expected graphs to start with an array", jp.getCurrentLocation(),
270+
reportError("Expected graphs to start with an array", jp.currentLocation(),
271271
RDFJSONParserSettings.SUPPORT_GRAPHS_EXTENSION);
272272
}
273273

@@ -279,49 +279,49 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
279279
reportError(
280280
"Unrecognised JSON field name for object: subject=" + subjStr + " predicate="
281281
+ predStr + " fieldname=" + fieldName,
282-
jp.getCurrentLocation(), RDFJSONParserSettings.FAIL_ON_UNKNOWN_PROPERTY);
282+
jp.currentLocation(), RDFJSONParserSettings.FAIL_ON_UNKNOWN_PROPERTY);
283283
}
284284
}
285285

286286
Value object = null;
287287

288288
if (nextType == null) {
289289
reportFatalError("No type for object: subject=" + subjStr + " predicate=" + predStr,
290-
jp.getCurrentLocation());
290+
jp.currentLocation());
291291
}
292292

293293
if (nextValue == null) {
294294
reportFatalError("No value for object: subject=" + subjStr + " predicate=" + predStr,
295-
jp.getCurrentLocation());
295+
jp.currentLocation());
296296
}
297297

298298
if (RDFJSONUtility.LITERAL.equals(nextType)) {
299299
if (nextLanguage != null) {
300-
object = this.createLiteral(nextValue, nextLanguage, null, jp.getCurrentLocation());
300+
object = this.createLiteral(nextValue, nextLanguage, null, jp.currentLocation());
301301
} else if (nextDatatype != null) {
302302
object = this.createLiteral(nextValue, null, this.createURI(nextDatatype),
303-
jp.getCurrentLocation());
303+
jp.currentLocation());
304304
} else {
305-
object = this.createLiteral(nextValue, null, null, jp.getCurrentLocation());
305+
object = this.createLiteral(nextValue, null, null, jp.currentLocation());
306306
}
307307
} else if (RDFJSONUtility.BNODE.equals(nextType)) {
308308
if (nextLanguage != null) {
309309
reportFatalError("Language was attached to a blank node object: subject=" + subjStr
310-
+ " predicate=" + predStr, jp.getCurrentLocation());
310+
+ " predicate=" + predStr, jp.currentLocation());
311311
}
312312
if (nextDatatype != null) {
313313
reportFatalError("Datatype was attached to a blank node object: subject=" + subjStr
314-
+ " predicate=" + predStr, jp.getCurrentLocation());
314+
+ " predicate=" + predStr, jp.currentLocation());
315315
}
316316
object = createNode(nextValue.substring(2));
317317
} else if (RDFJSONUtility.URI.equals(nextType)) {
318318
if (nextLanguage != null) {
319319
reportFatalError("Language was attached to a uri object: subject=" + subjStr + " predicate="
320-
+ predStr, jp.getCurrentLocation());
320+
+ predStr, jp.currentLocation());
321321
}
322322
if (nextDatatype != null) {
323323
reportFatalError("Datatype was attached to a uri object: subject=" + subjStr + " predicate="
324-
+ predStr, jp.getCurrentLocation());
324+
+ predStr, jp.currentLocation());
325325
}
326326
object = vf.createIRI(nextValue);
327327
}
@@ -353,12 +353,12 @@ private void rdfJsonToHandlerInternal(final RDFHandler handler, final ValueFacto
353353
}
354354
if (!foundObject) {
355355
reportFatalError("No object for predicate: subject=" + subjStr + " predicate=" + predStr,
356-
jp.getCurrentLocation());
356+
jp.currentLocation());
357357
}
358358
}
359359

360360
if (!foundPredicate) {
361-
reportFatalError("No predicate for object: subject=" + subjStr, jp.getCurrentLocation());
361+
reportFatalError("No predicate for object: subject=" + subjStr, jp.currentLocation());
362362
}
363363
}
364364
}
@@ -395,13 +395,12 @@ public Collection<RioSetting<?>> getSupportedSettings() {
395395
* @return A newly configured JsonFactory based on the currently enabled settings
396396
*/
397397
private JsonFactory configureNewJsonFactory() {
398-
JsonFactoryBuilder builder = new JsonFactoryBuilder();
398+
var builder = JsonFactory.builder();
399399
// Disable features that may work for most JSON where the field names are
400-
// in limited supply,
401-
// but does not work for RDF/JSON where a wide range of URIs are used for
402-
// subjects and predicates
403-
builder.disable(JsonFactory.Feature.INTERN_FIELD_NAMES);
404-
builder.disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES);
400+
// in limited supply, but does not work for RDF/JSON where a wide range of
401+
// URIs are used for subjects and predicates
402+
builder.disable(TokenStreamFactory.Feature.INTERN_PROPERTY_NAMES);
403+
builder.disable(TokenStreamFactory.Feature.CANONICALIZE_PROPERTY_NAMES);
405404
builder.disable(StreamWriteFeature.AUTO_CLOSE_TARGET);
406405

407406
if (getParserConfig().isSet(JSONSettings.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) {
@@ -429,7 +428,7 @@ private JsonFactory configureNewJsonFactory() {
429428
getParserConfig().get(JSONSettings.ALLOW_UNQUOTED_CONTROL_CHARS));
430429
}
431430
if (getParserConfig().isSet(JSONSettings.ALLOW_UNQUOTED_FIELD_NAMES)) {
432-
builder.configure(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES,
431+
builder.configure(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES,
433432
getParserConfig().get(JSONSettings.ALLOW_UNQUOTED_FIELD_NAMES));
434433
}
435434
if (getParserConfig().isSet(JSONSettings.ALLOW_YAML_COMMENTS)) {

0 commit comments

Comments
 (0)