json2: unescape characters (#6836)
parent
c8b7cfc297
commit
fe3d2a9aba
|
@ -223,8 +223,6 @@ fn (mut p Parser) decode_value() ?Any {
|
|||
fn (mut p Parser) decode_string() ?Any {
|
||||
mut strwr := strings.new_builder(200)
|
||||
for i := 0; i < p.tok.lit.len; i++ {
|
||||
// s := p.tok.lit[i].str()
|
||||
// println('$i $s')
|
||||
if ((i-1 >= 0 && p.tok.lit[i-1] != `/`) || i == 0) && int(p.tok.lit[i]) in [9, 10, 0] {
|
||||
return error('character must be escaped with a backslash.')
|
||||
}
|
||||
|
@ -235,8 +233,33 @@ fn (mut p Parser) decode_string() ?Any {
|
|||
|
||||
if i+1 < p.tok.lit.len && p.tok.lit[i] == 92 {
|
||||
peek := p.tok.lit[i+1]
|
||||
if peek in [`b`, `f`, `n`, `r`, `t`, `u`, `\\`, `"`, `/`] {
|
||||
if peek == `u` {
|
||||
match peek{
|
||||
`b` {
|
||||
i++
|
||||
strwr.write_b(`\b`)
|
||||
continue
|
||||
}
|
||||
`f` {
|
||||
i++
|
||||
strwr.write_b(`\f`)
|
||||
continue
|
||||
}
|
||||
`n` {
|
||||
i++
|
||||
strwr.write_b(`\n`)
|
||||
continue
|
||||
}
|
||||
`r` {
|
||||
i++
|
||||
strwr.write_b(`\r`)
|
||||
continue
|
||||
}
|
||||
`t` {
|
||||
i++
|
||||
strwr.write_b(`\t`)
|
||||
continue
|
||||
}
|
||||
`u` {
|
||||
if i+5 < p.tok.lit.len {
|
||||
codepoint := p.tok.lit[i+2..i+6]
|
||||
check_valid_hex(codepoint)?
|
||||
|
@ -248,13 +271,23 @@ fn (mut p Parser) decode_string() ?Any {
|
|||
return error('incomplete unicode escape.')
|
||||
}
|
||||
}
|
||||
|
||||
i++
|
||||
strwr.write_b(p.tok.lit[i])
|
||||
continue
|
||||
} else {
|
||||
return error('invalid backslash escape.')
|
||||
}
|
||||
`\\` {
|
||||
i++
|
||||
strwr.write_b(`\\`)
|
||||
continue
|
||||
}
|
||||
`"` {
|
||||
i++
|
||||
strwr.write_b(`\"`)
|
||||
continue
|
||||
}
|
||||
`/` {
|
||||
i++
|
||||
strwr.write_b(`/`)
|
||||
continue
|
||||
}
|
||||
else { return error('invalid backslash escape.') }
|
||||
}
|
||||
|
||||
if int(peek) == 85 {
|
||||
return error('unicode endpoints must be in lowercase `u`.')
|
||||
|
|
|
@ -7,7 +7,11 @@ import strings
|
|||
|
||||
fn write_value(v Any, i int, len int, mut wr strings.Builder) {
|
||||
str := v.str()
|
||||
wr.write(if v is string { '"$str"' } else { str })
|
||||
if v is string {
|
||||
wr.write('"$str"')
|
||||
} else {
|
||||
wr.write(str)
|
||||
}
|
||||
if i >= len-1 { return }
|
||||
wr.write_b(`,`)
|
||||
}
|
||||
|
|
|
@ -69,6 +69,28 @@ fn test_fast_raw_decode() {
|
|||
assert str == '{"name":"Peter","age":"28","salary":"95000.5","title":"2"}'
|
||||
}
|
||||
|
||||
fn test_character_unescape() {
|
||||
// Need to test `\r`, `\b`, `\f` ??
|
||||
message := '{
|
||||
"newline":"new\\nline",
|
||||
"tab":"\\ttab",
|
||||
"backslash": "back\\\\slash",
|
||||
"quotes": "\\"quotes\\"",
|
||||
"slash":"\/dev\/null"
|
||||
}'
|
||||
mut obj := json2.raw_decode(message) or {
|
||||
assert false
|
||||
json2.Any{}
|
||||
}
|
||||
lines := obj.as_map()
|
||||
eprintln("$lines")
|
||||
assert lines['newline'].str() == 'new\nline'
|
||||
assert lines['tab'].str() == '\ttab'
|
||||
assert lines['backslash'].str() == 'back\\slash'
|
||||
assert lines['quotes'].str() == '\"quotes\"'
|
||||
assert lines['slash'].str() == '/dev/null'
|
||||
}
|
||||
|
||||
/*
|
||||
struct User2 {
|
||||
age int
|
||||
|
|
Loading…
Reference in New Issue