rune_modules/
json.rs

1//! The native `json` module for the [Rune Language].
2//!
3//! [Rune Language]: https://rune-rs.github.io
4//!
5//! ## Usage
6//!
7//! Add the following to your `Cargo.toml`:
8//!
9//! ```toml
10//! rune-modules = { version = "0.14.0", features = ["json"] }
11//! ```
12//!
13//! Install it into your context:
14//!
15//! ```rust
16//! let mut context = rune::Context::with_default_modules()?;
17//! context.install(rune_modules::json::module(true)?)?;
18//! # Ok::<_, rune::support::Error>(())
19//! ```
20//!
21//! Use it in Rune:
22//!
23//! ```rust,ignore
24//! use json;
25//!
26//! fn main() {
27//!     let data = json::from_string("{\"key\": 42}");
28//!     dbg(data);
29//! }
30//! ```
31
32use rune::alloc::fmt::TryWrite;
33use rune::alloc::{String, Vec};
34use rune::runtime::{Bytes, Formatter, Value, VmResult};
35use rune::{vm_write, Any, ContextError, Module};
36
37#[rune::module(::json)]
38/// Module for processing JSON.
39///
40/// # Examples
41///
42/// ```rune
43/// let object = #{"number": 42, "string": "Hello World"};
44/// let object = json::from_string(json::to_string(object)?)?;
45/// assert_eq!(object, #{"number": 42, "string": "Hello World"});
46/// ```
47pub fn module(_stdio: bool) -> Result<Module, ContextError> {
48    let mut module = Module::from_meta(self::module_meta)?;
49    module.ty::<Error>()?;
50    module.function_meta(Error::display)?;
51    module.function_meta(Error::debug)?;
52    module.function_meta(from_bytes)?;
53    module.function_meta(from_string)?;
54    module.function_meta(to_string)?;
55    module.function_meta(to_bytes)?;
56    Ok(module)
57}
58
59#[derive(Any)]
60#[rune(item = ::json)]
61/// Error type raised during JSON serialization.
62struct Error {
63    error: serde_json::Error,
64}
65
66impl Error {
67    #[rune::function(protocol = DISPLAY_FMT)]
68    pub(crate) fn display(&self, f: &mut Formatter) -> VmResult<()> {
69        vm_write!(f, "{}", self.error)
70    }
71
72    #[rune::function(protocol = DEBUG_FMT)]
73    pub(crate) fn debug(&self, f: &mut Formatter) -> VmResult<()> {
74        vm_write!(f, "{:?}", self.error)
75    }
76}
77
78impl From<serde_json::Error> for Error {
79    fn from(error: serde_json::Error) -> Self {
80        Self { error }
81    }
82}
83
84/// Convert JSON bytes into a rune value.
85///
86/// # Examples
87///
88/// ```rune
89/// let object = json::from_bytes(b"{\"number\": 42, \"string\": \"Hello World\"}")?;
90/// assert_eq!(object, #{"number": 42, "string": "Hello World"});
91/// ```
92#[rune::function]
93fn from_bytes(bytes: &[u8]) -> Result<Value, Error> {
94    Ok(serde_json::from_slice(bytes)?)
95}
96
97/// Convert a JSON string into a rune value.
98///
99/// # Examples
100///
101/// ```rune
102/// let object = json::from_string("{\"number\": 42, \"string\": \"Hello World\"}")?;
103/// assert_eq!(object, #{"number": 42, "string": "Hello World"});
104/// ```
105#[rune::function]
106fn from_string(string: &str) -> Result<Value, Error> {
107    Ok(serde_json::from_str(string)?)
108}
109
110/// Convert any value to a json string.
111///
112/// # Examples
113///
114/// ```rune
115/// let object = #{"number": 42, "string": "Hello World"};
116/// let object = json::from_string(json::to_string(object)?)?;
117/// assert_eq!(object, #{"number": 42, "string": "Hello World"});
118/// ```
119#[rune::function(vm_result)]
120fn to_string(value: Value) -> Result<String, Error> {
121    Ok(String::try_from(serde_json::to_string(&value)?).vm?)
122}
123
124/// Convert any value to json bytes.
125///
126/// # Examples
127///
128/// ```rune
129/// let object = #{"number": 42, "string": "Hello World"};
130/// let object = json::from_bytes(json::to_bytes(object)?)?;
131/// assert_eq!(object, #{"number": 42, "string": "Hello World"});
132/// ```
133#[rune::function(vm_result)]
134fn to_bytes(value: Value) -> Result<Bytes, Error> {
135    Ok(Bytes::from_vec(
136        Vec::try_from(serde_json::to_vec(&value)?).vm?,
137    ))
138}