JSON query results: Ignore unknown keys

Allows to parse e.g. Virtuoso query results
pull/216/head
Tpt 2 years ago
parent 1f7e59dde7
commit 9c06f7f097
  1. 50
      lib/sparesults/src/json.rs
  2. 17
      testsuite/oxigraph-tests/sparql-results/ignored_keys.srj
  3. 13
      testsuite/oxigraph-tests/sparql-results/ignored_keys.srx
  4. 10
      testsuite/oxigraph-tests/sparql-results/manifest.ttl
  5. 16
      testsuite/src/sparql_evaluator.rs

@ -154,11 +154,17 @@ impl<R: BufRead> JsonQueryResultsReader<R> {
if reader.read_event(&mut buffer)? != JsonEvent::StartObject {
return Err(SyntaxError::msg("'results' should be an object").into());
}
if reader.read_event(&mut buffer)? != JsonEvent::ObjectKey("bindings") {
return Err(SyntaxError::msg(
"'results' should contain a 'bindings' key",
)
.into());
loop {
match reader.read_event(&mut buffer)? {
JsonEvent::ObjectKey("bindings") => break, // Found
JsonEvent::ObjectKey(_) => ignore_value(&mut reader, &mut buffer)?,
_ => {
return Err(SyntaxError::msg(
"'results' should contain a 'bindings' key",
)
.into())
}
}
}
if reader.read_event(&mut buffer)? != JsonEvent::StartArray {
return Err(SyntaxError::msg("'bindings' should be an object").into());
@ -495,14 +501,38 @@ fn read_head<R: BufRead>(
}
}
}
_ => {
return Err(
SyntaxError::msg(format!("Unexpected key in head: '{}'", key)).into(),
)
}
_ => ignore_value(reader, buffer)?,
},
JsonEvent::EndObject => return Ok(variables),
_ => return Err(SyntaxError::msg("Invalid head serialization").into()),
}
}
}
fn ignore_value<R: BufRead>(
reader: &mut JsonReader<R>,
buffer: &mut Vec<u8>,
) -> Result<(), ParseError> {
let mut nesting = 0;
loop {
match reader.read_event(buffer)? {
JsonEvent::Boolean(_)
| JsonEvent::Null
| JsonEvent::Number(_)
| JsonEvent::String(_) => {
if nesting == 0 {
return Ok(());
}
}
JsonEvent::ObjectKey(_) => (),
JsonEvent::StartArray | JsonEvent::StartObject => nesting += 1,
JsonEvent::EndArray | JsonEvent::EndObject => {
nesting -= 1;
if nesting == 0 {
return Ok(());
}
}
JsonEvent::Eof => return Err(SyntaxError::msg("Unexpected end of file").into()),
}
}
}

@ -0,0 +1,17 @@
{
"head": {
"vars": ["s"],
"custom": null
},
"results": {
"custom": {"foo": [true, false]},
"bindings": [
{
"s": {
"type": "uri",
"value": "http://example.org/s1"
}
}
]
}
}

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head custom="foo">
<variable name="s"/>
</head>
<results custom="foo">
<result>
<binding name="s">
<uri>http://example.com/a</uri>
</binding>
</result>
</results>
</sparql>

@ -11,6 +11,8 @@
:results_json_duplicated_variables
:results_xml_duplicated_variables
:results_tsv_duplicated_variables
:results_json_ignored_keys
:results_xml_ignored_keys
) .
:results_json_duplicated_variables rdf:type ox:NegativeJsonResultsSyntaxTest ;
@ -24,3 +26,11 @@
:results_xml_duplicated_variables rdf:type ox:NegativeTsvResultsSyntaxTest ;
mf:name "Duplicated variables are not allowed" ;
mf:action <duplicated_variables.tsv> .
:results_json_ignored_keys rdf:type ox:PositiveJsonResultsSyntaxTest ;
mf:name "Ignore unknown keys in objects" ;
mf:action <ignored_keys.srj> .
:results_xml_ignored_keys rdf:type ox:PositiveXmlResultsSyntaxTest ;
mf:name "Ignore unknown attributes on tags" ;
mf:action <ignored_keys.srx> .

@ -47,10 +47,18 @@ pub fn register_sparql_tests(evaluator: &mut TestEvaluator) {
"http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#UpdateEvaluationTest",
evaluate_update_evaluation_test,
);
evaluator.register(
"https://github.com/oxigraph/oxigraph/tests#PositiveJsonResultsSyntaxTest",
evaluate_positive_json_result_syntax_test,
);
evaluator.register(
"https://github.com/oxigraph/oxigraph/tests#NegativeJsonResultsSyntaxTest",
evaluate_negative_json_result_syntax_test,
);
evaluator.register(
"https://github.com/oxigraph/oxigraph/tests#PositiveXmlResultsSyntaxTest",
evaluate_positive_xml_result_syntax_test,
);
evaluator.register(
"https://github.com/oxigraph/oxigraph/tests#NegativeXmlResultsSyntaxTest",
evaluate_negative_xml_result_syntax_test,
@ -95,6 +103,10 @@ fn evaluate_negative_syntax_test(test: &Test) -> Result<()> {
}
}
fn evaluate_positive_json_result_syntax_test(test: &Test) -> Result<()> {
result_syntax_check(test, QueryResultsFormat::Json)
}
fn evaluate_negative_json_result_syntax_test(test: &Test) -> Result<()> {
if result_syntax_check(test, QueryResultsFormat::Json).is_ok() {
Err(anyhow!("Oxigraph parses even if it should not {}.", test))
@ -103,6 +115,10 @@ fn evaluate_negative_json_result_syntax_test(test: &Test) -> Result<()> {
}
}
fn evaluate_positive_xml_result_syntax_test(test: &Test) -> Result<()> {
result_syntax_check(test, QueryResultsFormat::Xml)
}
fn evaluate_negative_xml_result_syntax_test(test: &Test) -> Result<()> {
if result_syntax_check(test, QueryResultsFormat::Xml).is_ok() {
Err(anyhow!("Oxigraph parses even if it should not {}.", test))

Loading…
Cancel
Save