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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy