mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-30 10:56:09 +03:00
Update the JSON parser to account for fabricereix changes
This commit is contained in:
parent
e0d9bb929e
commit
97a02f3990
@ -1,7 +1,7 @@
|
|||||||
error: Parsing JSON
|
error: Parsing JSON
|
||||||
--> tests_error_parser/json.hurl:2:1
|
--> tests_error_parser/json.hurl:3:1
|
||||||
|
|
|
|
||||||
2 | { "name":
|
3 | HTTP 200
|
||||||
| ^ this brace is not closed later
|
| ^ expecting a boolean, number, string, array, object or null
|
||||||
|
|
|
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
error: Parsing JSON
|
||||||
|
--> tests_error_parser/json_list_expecting_element.hurl:3:17
|
||||||
|
|
|
||||||
|
3 | "name": ["c", x
|
||||||
|
| ^ expecting a boolean, number, string, array, object or null
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
POST http://localhost:8000/data
|
||||||
|
{
|
||||||
|
"name": ["c", x
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
Set-StrictMode -Version latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
hurl tests_error_parser/json_list_expecting_element.hurl
|
3
integration/tests_error_parser/json_list_expecting_element.sh
Executable file
3
integration/tests_error_parser/json_list_expecting_element.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
hurl tests_error_parser/json_list_expecting_element.hurl
|
@ -0,0 +1,7 @@
|
|||||||
|
error: Parsing JSON
|
||||||
|
--> tests_error_parser/json_list_trailing_comma.hurl:3:20
|
||||||
|
|
|
||||||
|
3 | "name": ["c", "d", ]
|
||||||
|
| ^ trailing comma is not allowed
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
2
|
@ -0,0 +1,4 @@
|
|||||||
|
POST http://localhost:8000/data
|
||||||
|
{
|
||||||
|
"name": ["c", "d", ]
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
Set-StrictMode -Version latest
|
Set-StrictMode -Version latest
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
hurl tests_error_parser/json_unexpected_character.hurl
|
hurl tests_error_parser/json_list_trailing_comma.hurl
|
3
integration/tests_error_parser/json_list_trailing_comma.sh
Executable file
3
integration/tests_error_parser/json_list_trailing_comma.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
hurl tests_error_parser/json_list_trailing_comma.hurl
|
@ -0,0 +1,7 @@
|
|||||||
|
error: Parsing JSON
|
||||||
|
--> tests_error_parser/json_object_expecting_element.hurl:2:11
|
||||||
|
|
|
||||||
|
2 | { "name": x
|
||||||
|
| ^ expecting a boolean, number, string, array, object or null
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
2
|
@ -0,0 +1,3 @@
|
|||||||
|
Set-StrictMode -Version latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
hurl tests_error_parser/json_object_expecting_element.hurl
|
3
integration/tests_error_parser/json_object_expecting_element.sh
Executable file
3
integration/tests_error_parser/json_object_expecting_element.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
hurl tests_error_parser/json_object_expecting_element.hurl
|
@ -0,0 +1,7 @@
|
|||||||
|
error: Parsing JSON
|
||||||
|
--> tests_error_parser/json_object_trailing_comma.hurl:5:13
|
||||||
|
|
|
||||||
|
5 | "c": "d",
|
||||||
|
| ^ trailing comma is not allowed
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
2
|
@ -0,0 +1,7 @@
|
|||||||
|
POST http://localhost:8000/data
|
||||||
|
{
|
||||||
|
"toto": {
|
||||||
|
"a": "b",
|
||||||
|
"c": "d",
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
Set-StrictMode -Version latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
hurl tests_error_parser/json_object_trailing_comma.hurl
|
3
integration/tests_error_parser/json_object_trailing_comma.sh
Executable file
3
integration/tests_error_parser/json_object_trailing_comma.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
hurl tests_error_parser/json_object_trailing_comma.hurl
|
@ -1,7 +0,0 @@
|
|||||||
error: Parsing JSON
|
|
||||||
--> tests_error_parser/json_unexpected_character.hurl:2:1
|
|
||||||
|
|
|
||||||
2 | { "name": x
|
|
||||||
| ^ this brace is not closed later
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -Eeuo pipefail
|
|
||||||
hurl tests_error_parser/json_unexpected_character.hurl
|
|
@ -1,7 +1,7 @@
|
|||||||
error: Parsing JSON
|
error: Parsing JSON
|
||||||
--> tests_error_parser/json_unexpected_eof.hurl:2:1
|
--> tests_error_parser/json_unexpected_eof.hurl:2:10
|
||||||
|
|
|
|
||||||
2 | { "name":
|
2 | { "name":
|
||||||
| ^ this brace is not closed later
|
| ^ expecting an element; found empty element instead
|
||||||
|
|
|
|
||||||
|
|
||||||
|
@ -96,12 +96,9 @@ impl Error for parser::Error {
|
|||||||
ParseError::TemplateVariable => "expecting a variable".to_string(),
|
ParseError::TemplateVariable => "expecting a variable".to_string(),
|
||||||
ParseError::Json(variant) => {
|
ParseError::Json(variant) => {
|
||||||
match variant {
|
match variant {
|
||||||
JsonErrorVariant::UnexpectedCharcter { character } => format!("unexpected character: '{character}'"),
|
JsonErrorVariant::TrailingComma => "trailing comma is not allowed".to_string(),
|
||||||
JsonErrorVariant::EmptyElement => "expecting an element; found empty element instead".to_string(),
|
JsonErrorVariant::EmptyElement => "expecting an element; found empty element instead".to_string(),
|
||||||
JsonErrorVariant::UnclosedBrace => "this brace is not closed later".to_string(),
|
JsonErrorVariant::ExpectingElement => "expecting a boolean, number, string, array, object or null".to_string(),
|
||||||
JsonErrorVariant::CannotResolve { name } => {
|
|
||||||
format!("failed to resolve '{name}'. If it's a variable, try enclosing it with double braces, e.g. {{{{{name}}}}}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParseError::Predicate => "expecting a predicate".to_string(),
|
ParseError::Predicate => "expecting a predicate".to_string(),
|
||||||
|
@ -148,10 +148,12 @@ mod tests {
|
|||||||
fn test_bytes_json_error() {
|
fn test_bytes_json_error() {
|
||||||
let mut reader = Reader::new("{ x ");
|
let mut reader = Reader::new("{ x ");
|
||||||
let error = bytes(&mut reader).err().unwrap();
|
let error = bytes(&mut reader).err().unwrap();
|
||||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
assert_eq!(error.pos, Pos { line: 1, column: 3 });
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.inner,
|
error.inner,
|
||||||
ParseError::Json(JsonErrorVariant::UnclosedBrace)
|
ParseError::Expecting {
|
||||||
|
value: "\"".to_string()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,10 +67,9 @@ pub enum ParseError {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum JsonErrorVariant {
|
pub enum JsonErrorVariant {
|
||||||
UnexpectedCharcter { character: String },
|
TrailingComma,
|
||||||
CannotResolve { name: String },
|
ExpectingElement,
|
||||||
EmptyElement,
|
EmptyElement,
|
||||||
UnclosedBrace,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
@ -57,23 +57,16 @@ fn parse_in_json(reader: &mut Reader) -> ParseResult<JsonValue> {
|
|||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
Error {
|
Error {
|
||||||
recoverable: true, ..
|
recoverable: true, ..
|
||||||
} => {
|
} => Err(error::Error {
|
||||||
return Err(error::Error {
|
|
||||||
pos: e.pos,
|
pos: e.pos,
|
||||||
recoverable: false,
|
recoverable: false,
|
||||||
inner: error::ParseError::Json(JsonErrorVariant::CannotResolve {
|
inner: error::ParseError::Json(JsonErrorVariant::ExpectingElement),
|
||||||
name: reader
|
|
||||||
.read_while(|c| !c.is_whitespace() && !c.is_ascii_punctuation()),
|
|
||||||
}),
|
}),
|
||||||
})
|
_ => Err(Error {
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(Error {
|
|
||||||
recoverable: false,
|
recoverable: false,
|
||||||
pos: e.pos,
|
pos: e.pos,
|
||||||
inner: e.inner,
|
inner: e.inner,
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,9 +297,7 @@ fn list_value(reader: &mut Reader) -> ParseResult<JsonValue> {
|
|||||||
return Err(Error {
|
return Err(Error {
|
||||||
pos: save,
|
pos: save,
|
||||||
recoverable: false,
|
recoverable: false,
|
||||||
inner: ParseError::Json(JsonErrorVariant::UnexpectedCharcter {
|
inner: ParseError::Json(JsonErrorVariant::TrailingComma),
|
||||||
character: ','.to_string(),
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let element = list_element(reader)?;
|
let element = list_element(reader)?;
|
||||||
@ -330,9 +321,7 @@ fn list_element(reader: &mut Reader) -> ParseResult<JsonListElement> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn object_value(reader: &mut Reader) -> ParseResult<JsonValue> {
|
pub fn object_value(reader: &mut Reader) -> ParseResult<JsonValue> {
|
||||||
let save = reader.state.clone();
|
|
||||||
try_literal("{", reader)?;
|
try_literal("{", reader)?;
|
||||||
peek_until_close_brace(reader, save)?;
|
|
||||||
let space0 = whitespace(reader);
|
let space0 = whitespace(reader);
|
||||||
let mut elements = vec![];
|
let mut elements = vec![];
|
||||||
if reader.peek() != Some('}') {
|
if reader.peek() != Some('}') {
|
||||||
@ -358,9 +347,7 @@ pub fn object_value(reader: &mut Reader) -> ParseResult<JsonValue> {
|
|||||||
return Err(Error {
|
return Err(Error {
|
||||||
pos: save,
|
pos: save,
|
||||||
recoverable: false,
|
recoverable: false,
|
||||||
inner: ParseError::Json(JsonErrorVariant::UnexpectedCharcter {
|
inner: ParseError::Json(JsonErrorVariant::TrailingComma),
|
||||||
character: ','.to_string(),
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let element = object_element(reader)?;
|
let element = object_element(reader)?;
|
||||||
@ -388,6 +375,7 @@ fn key(reader: &mut Reader) -> ParseResult<Template> {
|
|||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_element(reader: &mut Reader) -> ParseResult<JsonObjectElement> {
|
fn object_element(reader: &mut Reader) -> ParseResult<JsonObjectElement> {
|
||||||
let space0 = whitespace(reader);
|
let space0 = whitespace(reader);
|
||||||
//literal("\"", reader)?;
|
//literal("\"", reader)?;
|
||||||
@ -424,34 +412,6 @@ fn whitespace(reader: &mut Reader) -> String {
|
|||||||
reader.read_while(|c| *c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')
|
reader.read_while(|c| *c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper to find if the user forgot to place a close brace, e.g. `{"a":\n`.
|
|
||||||
fn peek_until_close_brace(reader: &mut Reader, state: ReaderState) -> ParseResult<()> {
|
|
||||||
let mut offset = state.cursor;
|
|
||||||
// It's necessary to count the open braces found, because something like `{"a" : {"b": 1}` has
|
|
||||||
// a closing brace but the user still forgot to place the last brace.
|
|
||||||
let mut open_braces_found = 0;
|
|
||||||
loop {
|
|
||||||
if let Some(c) = reader.buffer.get(offset).copied() {
|
|
||||||
if c == '{' {
|
|
||||||
open_braces_found += 1;
|
|
||||||
} else if c == '}' {
|
|
||||||
if open_braces_found > 0 {
|
|
||||||
open_braces_found -= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(Error {
|
|
||||||
pos: state.pos,
|
|
||||||
recoverable: false,
|
|
||||||
inner: ParseError::Json(JsonErrorVariant::UnclosedBrace),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
offset += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -473,9 +433,7 @@ mod tests {
|
|||||||
assert_eq!(error.pos, Pos { line: 1, column: 5 });
|
assert_eq!(error.pos, Pos { line: 1, column: 5 });
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.inner,
|
error.inner,
|
||||||
error::ParseError::Json(JsonErrorVariant::UnexpectedCharcter {
|
error::ParseError::Json(JsonErrorVariant::TrailingComma),
|
||||||
character: ','.to_string(),
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
assert!(!error.recoverable);
|
assert!(!error.recoverable);
|
||||||
}
|
}
|
||||||
@ -874,9 +832,7 @@ mod tests {
|
|||||||
assert_eq!(error.pos, Pos { line: 1, column: 6 });
|
assert_eq!(error.pos, Pos { line: 1, column: 6 });
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.inner,
|
error.inner,
|
||||||
error::ParseError::Json(JsonErrorVariant::UnexpectedCharcter {
|
error::ParseError::Json(JsonErrorVariant::TrailingComma),
|
||||||
character: ','.to_string(),
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
assert!(!error.recoverable);
|
assert!(!error.recoverable);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ pub fn parse_hurl_file(s: &str) -> ParseResult<HurlFile> {
|
|||||||
parsers::hurl_file(&mut reader)
|
parsers::hurl_file(&mut reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::error::{Error, ParseError, JsonErrorVariant};
|
pub use self::error::{Error, JsonErrorVariant, ParseError};
|
||||||
pub use self::json::{
|
pub use self::json::{
|
||||||
boolean_value as parse_json_boolean, null_value as parse_json_null,
|
boolean_value as parse_json_boolean, null_value as parse_json_null,
|
||||||
number_value as parse_json_number, parse as parse_json,
|
number_value as parse_json_number, parse as parse_json,
|
||||||
|
@ -598,7 +598,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut reader = Reader::new("{x");
|
let mut reader = Reader::new("{x");
|
||||||
let error = body(&mut reader).err().unwrap();
|
let error = body(&mut reader).err().unwrap();
|
||||||
assert_eq!(error.pos, Pos { line: 1, column: 1 });
|
assert_eq!(error.pos, Pos { line: 1, column: 2 });
|
||||||
assert!(!error.recoverable);
|
assert!(!error.recoverable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user