Add tests for json_load and json_loads of bytes and bytearray

This commit is contained in:
Daehee Kim
2019-08-15 20:03:11 +09:00
committed by zsaladin
parent 04ac07126d
commit a010bc9b95
2 changed files with 67 additions and 24 deletions

View File

@@ -1,6 +1,6 @@
from testutils import assert_raises
import json
from io import StringIO
from io import StringIO, BytesIO
def round_trip_test(obj):
# serde_json and Python's json module produce slightly differently spaced
@@ -15,7 +15,7 @@ def json_dump(obj):
return f.getvalue()
def json_load(obj):
f = StringIO(obj)
f = StringIO(obj) if isinstance(obj, str) else BytesIO(bytes(obj))
return json.load(f)
assert '"string"' == json.dumps("string")
@@ -70,42 +70,92 @@ assert_raises(json.JSONDecodeError, lambda: json_load('{3: "abc"}'))
assert json.dumps({'3': 'abc'}) == json.dumps({3: 'abc'})
assert 1 == json.loads("1")
assert 1 == json.loads(b"1")
assert 1 == json.loads(bytearray(b"1"))
assert 1 == json_load("1")
assert 1 == json_load(b"1")
assert 1 == json_load(bytearray(b"1"))
assert -1 == json.loads("-1")
assert -1 == json.loads(b"-1")
assert -1 == json.loads(bytearray(b"-1"))
assert -1 == json_load("-1")
assert -1 == json_load(b"-1")
assert -1 == json_load(bytearray(b"-1"))
assert 1.0 == json.loads("1.0")
assert 1.0 == json.loads(b"1.0")
assert 1.0 == json.loads(bytearray(b"1.0"))
assert 1.0 == json_load("1.0")
assert 1.0 == json_load(b"1.0")
assert 1.0 == json_load(bytearray(b"1.0"))
assert -1.0 == json.loads("-1.0")
assert -1.0 == json.loads(b"-1.0")
assert -1.0 == json.loads(bytearray(b"-1.0"))
assert -1.0 == json_load("-1.0")
assert -1.0 == json_load(b"-1.0")
assert -1.0 == json_load(bytearray(b"-1.0"))
assert "str" == json.loads('"str"')
assert "str" == json.loads(b'"str"')
assert "str" == json.loads(bytearray(b'"str"'))
assert "str" == json_load('"str"')
assert "str" == json_load(b'"str"')
assert "str" == json_load(bytearray(b'"str"'))
assert True is json.loads('true')
assert True is json.loads(b'true')
assert True is json.loads(bytearray(b'true'))
assert True is json_load('true')
assert True is json_load(b'true')
assert True is json_load(bytearray(b'true'))
assert False is json.loads('false')
assert False is json.loads(b'false')
assert False is json.loads(bytearray(b'false'))
assert False is json_load('false')
assert False is json_load(b'false')
assert False is json_load(bytearray(b'false'))
assert None is json.loads('null')
assert None is json.loads(b'null')
assert None is json.loads(bytearray(b'null'))
assert None is json_load('null')
assert None is json_load(b'null')
assert None is json_load(bytearray(b'null'))
assert [] == json.loads('[]')
assert [] == json.loads(b'[]')
assert [] == json.loads(bytearray(b'[]'))
assert [] == json_load('[]')
assert [] == json_load(b'[]')
assert [] == json_load(bytearray(b'[]'))
assert ['a'] == json.loads('["a"]')
assert ['a'] == json.loads(b'["a"]')
assert ['a'] == json.loads(bytearray(b'["a"]'))
assert ['a'] == json_load('["a"]')
assert ['a'] == json_load(b'["a"]')
assert ['a'] == json_load(bytearray(b'["a"]'))
assert [['a'], 'b'] == json.loads('[["a"], "b"]')
assert [['a'], 'b'] == json.loads(b'[["a"], "b"]')
assert [['a'], 'b'] == json.loads(bytearray(b'[["a"], "b"]'))
assert [['a'], 'b'] == json_load('[["a"], "b"]')
assert [['a'], 'b'] == json_load(b'[["a"], "b"]')
assert [['a'], 'b'] == json_load(bytearray(b'[["a"], "b"]'))
class String(str): pass
class Bytes(bytes): pass
class ByteArray(bytearray): pass
assert "string" == json.loads(String('"string"'))
assert "string" == json.loads(Bytes(b'"string"'))
assert "string" == json.loads(ByteArray(b'"string"'))
assert "string" == json_load(String('"string"'))
assert "string" == json_load(Bytes(b'"string"'))
assert "string" == json_load(ByteArray(b'"string"'))
assert '"string"' == json.dumps(String("string"))
assert '"string"' == json_dump(String("string"))

View File

@@ -1,6 +1,6 @@
use crate::obj::objbyteinner;
use crate::obj::objstr;
use crate::obj::objtype;
use crate::obj::objbytearray::PyByteArray;
use crate::obj::objbytes::PyBytes;
use crate::obj::objstr::PyString;
use crate::py_serde;
use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, TypeProtocol};
use crate::types::create_type;
@@ -21,25 +21,18 @@ pub fn json_dump(obj: PyObjectRef, fs: PyObjectRef, vm: &VirtualMachine) -> PyRe
/// Implement json.loads
pub fn json_loads(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
// TODO: Implement non-trivial deserialization case
let string = if objtype::isinstance(&obj, &vm.ctx.str_type()) {
objstr::get_value(&obj)
} else if objtype::isinstance(&obj, &vm.ctx.bytearray_type())
|| objtype::isinstance(&obj, &vm.ctx.bytes_type())
{
let bytes = objbyteinner::try_as_byte(&obj).unwrap();
String::from_utf8(bytes.to_vec()).map_err(|err| vm.new_type_error(err.to_string()))?
} else {
let msg = format!(
"the JSON object must be str, bytes or bytearray, not {}",
obj.class().name
);
return Err(vm.new_type_error(msg));
};
let de_result =
py_serde::deserialize(vm, &mut serde_json::Deserializer::from_str(string.as_str()));
let de_result = match_class!(obj,
s @ PyString => py_serde::deserialize(vm, &mut serde_json::Deserializer::from_str(s.as_str())),
b @ PyBytes => py_serde::deserialize(vm, &mut serde_json::Deserializer::from_slice(&b)),
ba @ PyByteArray => py_serde::deserialize(vm, &mut serde_json::Deserializer::from_slice(&ba.inner.borrow().elements)),
obj => {
let msg = format!(
"the JSON object must be str, bytes or bytearray, not {}",
obj.class().name
);
return Err(vm.new_type_error(msg));
}
);
de_result.map_err(|err| {
let module = vm
.get_attribute(vm.sys_module.clone(), "modules")