Skip to content

Commit 2a02e46

Browse files
authored
Added more support for JSON (#787)
1 parent 7361e32 commit 2a02e46

File tree

3 files changed

+115
-104
lines changed

3 files changed

+115
-104
lines changed

pgml-sdks/rust/pgml/src/languages/javascript.rs

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -107,51 +107,40 @@ impl IntoJsResult for DateTime {
107107
}
108108
}
109109

110-
// impl IntoJsResult for JsonHashMap {
111-
// type Output = JsObject;
112-
// fn into_js_result<'a, 'b, 'c: 'b, C: Context<'c>>(
113-
// self,
114-
// cx: &mut C,
115-
// ) -> JsResult<'b, Self::Output> {
116-
// self.0 .0.into_js_result(cx)
117-
// }
118-
// }
119-
120110
impl IntoJsResult for Json {
121-
type Output = JsObject;
111+
type Output = JsValue;
122112
fn into_js_result<'a, 'b, 'c: 'b, C: Context<'c>>(
123113
self,
124114
cx: &mut C,
125115
) -> JsResult<'b, Self::Output> {
126-
let js_object = JsObject::new(cx);
127-
for (k, v) in self
128-
.0
129-
.as_object()
130-
.expect("We currently only support json objects")
131-
.iter()
132-
{
133-
let js_key = cx.string(k);
134-
match v {
135-
// TODO: Support more types like nested objects
136-
serde_json::Value::Number(x) => {
137-
let js_value = x
138-
.as_f64()
139-
.expect("Error converting to f64 in impl IntoJsResult for Json");
140-
let js_value = JsNumber::new(cx, js_value);
141-
js_object.set(cx, js_key, js_value)?;
116+
match self.0 {
117+
serde_json::Value::Bool(x) => Ok(JsBoolean::new(cx, x).upcast()),
118+
serde_json::Value::Number(x) => Ok(JsNumber::new(
119+
cx,
120+
x.as_f64()
121+
.expect("Error converting to f64 in impl IntoJsResult for Json"),
122+
)
123+
.upcast()),
124+
serde_json::Value::String(x) => Ok(JsString::new(cx, &x).upcast()),
125+
serde_json::Value::Array(x) => {
126+
let js_array = JsArray::new(cx, x.len() as u32);
127+
for (i, v) in x.into_iter().enumerate() {
128+
let js_value = Json::into_js_result(Self(v), cx)?;
129+
js_array.set(cx, i as u32, js_value)?;
142130
}
143-
serde_json::Value::Bool(x) => {
144-
let js_value = JsBoolean::new(cx, *x);
145-
js_object.set(cx, js_key, js_value)?;
146-
}
147-
serde_json::Value::String(x) => {
148-
let js_value = cx.string(x);
131+
Ok(js_array.upcast())
132+
}
133+
serde_json::Value::Object(x) => {
134+
let js_object = JsObject::new(cx);
135+
for (k, v) in x.into_iter() {
136+
let js_key = cx.string(k);
137+
let js_value = Json::into_js_result(Self(v), cx)?;
149138
js_object.set(cx, js_key, js_value)?;
150139
}
151-
_ => {}
140+
Ok(js_object.upcast())
152141
}
142+
_ => panic!("Unsupported type for JSON conversion"),
153143
}
154-
Ok(js_object)
155144
}
156145
}
157146

@@ -303,36 +292,47 @@ impl<K: FromJsType + std::hash::Hash + std::fmt::Display + std::cmp::Eq, V: From
303292
}
304293

305294
impl FromJsType for Json {
306-
type From = JsObject;
295+
type From = JsValue;
307296
fn from_js_type<'a, C: Context<'a>>(cx: &mut C, arg: Handle<Self::From>) -> NeonResult<Self> {
308-
let mut json = serde_json::Map::new();
309-
let keys = arg.get_own_property_names(cx)?.to_vec(cx)?;
310-
for key in keys {
311-
let key: Handle<JsString> = key.downcast(cx).or_throw(cx)?;
312-
let key: String = String::from_js_type(cx, key)?;
313-
let value: Handle<JsValue> = arg.get(cx, key.as_str())?;
314-
// TODO: Support for more types
315-
if value.is_a::<JsString, _>(cx) {
316-
let value: Handle<JsString> = value.downcast(cx).or_throw(cx)?;
317-
let value: String = String::from_js_type(cx, value)?;
318-
let value = serde_json::Value::String(value);
319-
json.insert(key, value);
320-
} else if value.is_a::<JsNumber, _>(cx) {
321-
let value: Handle<JsNumber> = value.downcast(cx).or_throw(cx)?;
322-
let value: f64 = f64::from_js_type(cx, value)?;
323-
let value = serde_json::value::Number::from_f64(value)
324-
.expect("Could not convert f64 to serde_json::Number");
325-
let value = serde_json::value::Value::Number(value);
326-
json.insert(key, value);
327-
} else if value.is_a::<JsBoolean, _>(cx) {
328-
let value: Handle<JsBoolean> = value.downcast(cx).or_throw(cx)?;
329-
let value: bool = bool::from_js_type(cx, value)?;
330-
let value = serde_json::Value::Bool(value);
331-
json.insert(key, value);
332-
} else {
333-
panic!("Unsupported type for json conversion");
297+
if arg.is_a::<JsArray, _>(cx) {
298+
let value: Handle<JsArray> = arg.downcast(cx).or_throw(cx)?;
299+
let mut json = Vec::new();
300+
for item in value.to_vec(cx)? {
301+
let item = Json::from_js_type(cx, item)?;
302+
json.push(item.0);
303+
}
304+
Ok(Self(serde_json::Value::Array(json)))
305+
} else if arg.is_a::<JsBoolean, _>(cx) {
306+
let value: Handle<JsBoolean> = arg.downcast(cx).or_throw(cx)?;
307+
let value = bool::from_js_type(cx, value)?;
308+
let value = serde_json::Value::Bool(value);
309+
Ok(Self(value))
310+
} else if arg.is_a::<JsString, _>(cx) {
311+
let value: Handle<JsString> = arg.downcast(cx).or_throw(cx)?;
312+
let value = String::from_js_type(cx, value)?;
313+
let value = serde_json::Value::String(value);
314+
Ok(Self(value))
315+
} else if arg.is_a::<JsNumber, _>(cx) {
316+
let value: Handle<JsNumber> = arg.downcast(cx).or_throw(cx)?;
317+
let value = f64::from_js_type(cx, value)?;
318+
let value = serde_json::value::Number::from_f64(value)
319+
.expect("Could not convert f64 to serde_json::Number");
320+
let value = serde_json::value::Value::Number(value);
321+
Ok(Self(value))
322+
} else if arg.is_a::<JsObject, _>(cx) {
323+
let value: Handle<JsObject> = arg.downcast(cx).or_throw(cx)?;
324+
let mut json = serde_json::Map::new();
325+
let keys = value.get_own_property_names(cx)?.to_vec(cx)?;
326+
for key in keys {
327+
let key: Handle<JsString> = key.downcast(cx).or_throw(cx)?;
328+
let key: String = String::from_js_type(cx, key)?;
329+
let json_value: Handle<JsValue> = value.get(cx, key.as_str())?;
330+
let json_value = Json::from_js_type(cx, json_value)?;
331+
json.insert(key, json_value.0);
334332
}
333+
Ok(Self(serde_json::Value::Object(json)))
334+
} else {
335+
panic!("Unsupported type for Json conversion");
335336
}
336-
Ok(Self(serde_json::Value::Object(json)))
337337
}
338338
}
Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use pyo3::types::{PyDict, PyFloat, PyInt, PyString};
1+
use pyo3::types::{PyDict, PyFloat, PyInt, PyList, PyString};
22
use pyo3::{prelude::*, types::PyBool};
33

44
use crate::types::{DateTime, Json};
@@ -14,22 +14,26 @@ impl ToPyObject for DateTime {
1414

1515
impl ToPyObject for Json {
1616
fn to_object(&self, py: Python) -> PyObject {
17-
let dict = PyDict::new(py);
18-
for (k, v) in self
19-
.0
20-
.as_object()
21-
.expect("We currently only support json objects")
22-
.iter()
23-
{
24-
match v {
25-
// TODO: Support more types like nested objects
26-
serde_json::Value::Number(x) => dict.set_item(k, x.as_i64().unwrap()).unwrap(),
27-
serde_json::Value::Bool(x) => dict.set_item(k, x).unwrap(),
28-
serde_json::Value::String(x) => dict.set_item(k, x).unwrap(),
29-
_ => {}
30-
}
17+
match &self.0 {
18+
serde_json::Value::Bool(x) => x.to_object(py),
19+
serde_json::Value::Number(x) => x.as_f64().to_object(py),
20+
serde_json::Value::String(x) => x.to_object(py),
21+
serde_json::Value::Array(x) => {
22+
let list = PyList::empty(py);
23+
for v in x.iter() {
24+
list.append(Json(v.clone()).to_object(py)).unwrap();
25+
}
26+
list.to_object(py)
27+
},
28+
serde_json::Value::Object(x) => {
29+
let dict = PyDict::new(py);
30+
for (k, v) in x.iter() {
31+
dict.set_item(k, Json(v.clone()).to_object(py)).unwrap();
32+
}
33+
dict.to_object(py)
34+
},
35+
_ => panic!("Unsupported type for JSON conversion")
3136
}
32-
dict.to_object(py)
3337
}
3438
}
3539

@@ -38,31 +42,38 @@ impl ToPyObject for Json {
3842
////////////////////////////////////////////////////////////////////////////////
3943
impl FromPyObject<'_> for Json {
4044
fn extract(ob: &PyAny) -> PyResult<Self> {
41-
let dict: &PyDict = ob.downcast()?;
42-
let mut json = serde_json::Map::new();
43-
for (key, value) in dict.iter() {
44-
// TODO: Support more types
45-
if value.is_instance_of::<PyBool>()? {
46-
let value = bool::extract(value)?;
47-
json.insert(String::extract(key)?, serde_json::Value::Bool(value));
48-
} else if value.is_instance_of::<PyInt>()? {
49-
let value = i64::extract(value)?;
50-
json.insert(
51-
String::extract(key)?,
52-
serde_json::Value::Number(value.into()),
53-
);
54-
} else if value.is_instance_of::<PyFloat>()? {
55-
let value = f64::extract(value)?;
56-
let value = serde_json::value::Number::from_f64(value)
57-
.expect("Could not convert f64 to serde_json::Number");
58-
json.insert(String::extract(key)?, serde_json::Value::Number(value));
59-
} else if value.is_instance_of::<PyString>()? {
60-
let value = String::extract(value)?;
61-
json.insert(String::extract(key)?, serde_json::Value::String(value));
62-
} else {
63-
panic!("Unsupported type for json conversion");
45+
if ob.is_instance_of::<PyDict>()? {
46+
let dict: &PyDict = ob.downcast()?;
47+
let mut json = serde_json::Map::new();
48+
for (key, value) in dict.iter() {
49+
let value = Json::extract(value)?;
50+
json.insert(String::extract(key)?, value.0);
51+
}
52+
Ok(Self(serde_json::Value::Object(json)))
53+
} else if ob.is_instance_of::<PyBool>()? {
54+
let value = bool::extract(ob)?;
55+
Ok(Self(serde_json::Value::Bool(value)))
56+
} else if ob.is_instance_of::<PyInt>()? {
57+
let value = i64::extract(ob)?;
58+
Ok(Self(serde_json::Value::Number(value.into())))
59+
} else if ob.is_instance_of::<PyFloat>()? {
60+
let value = f64::extract(ob)?;
61+
let value = serde_json::value::Number::from_f64(value)
62+
.expect("Could not convert f64 to serde_json::Number");
63+
Ok(Self(serde_json::Value::Number(value)))
64+
} else if ob.is_instance_of::<PyString>()? {
65+
let value = String::extract(ob)?;
66+
Ok(Self(serde_json::Value::String(value)))
67+
} else if ob.is_instance_of::<PyList>()? {
68+
let value = ob.downcast::<PyList>()?;
69+
let mut json_values = Vec::new();
70+
for v in value {
71+
let v = v.extract::<Json>()?;
72+
json_values.push(v.0);
6473
}
74+
Ok(Self(serde_json::Value::Array(json_values)))
75+
} else {
76+
panic!("Unsupported type for JSON conversion");
6577
}
66-
Ok(Self(serde_json::Value::Object(json)))
6778
}
6879
}

pgml-sdks/rust/pgml/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn get_or_set_runtime<'a>() -> &'a Runtime {
7171
fn pgml(_py: Python, m: &PyModule) -> PyResult<()> {
7272
// We may want to move this into the new function in the DatabasePython struct and give the
7373
// user the oppertunity to pass in the log level filter
74-
init_logger(LevelFilter::Info).unwrap();
74+
init_logger(LevelFilter::Error).unwrap();
7575
m.add_class::<database::DatabasePython>()?;
7676
Ok(())
7777
}

0 commit comments

Comments
 (0)