yojson_rs/lib.rs
1//! # Yojson parser
2//! [![crates.io][crates-badge]][crates]
3//! [![docs.rs][docs-badge]][docs]
4//! [![Build Status][ci-badge]][ci]
5//! [![source badge][source-badge]][source]
6//! [![license badge][license-badge]][license]
7//!
8//! [crates]: https://crates.io/crates/yojson-rs
9//! [crates-badge]: https://img.shields.io/crates/v/yojson-rs
10//! [docs]: https://docs.rs/yojson-rs/
11//! [docs-badge]: https://img.shields.io/badge/docs.rs-yojson_rs-blue
12//! [ci]: https://github.com/puripuri2100/yojson-rs/actions?query=workflow%3ACI
13//! [ci-badge]: https://github.com/puripuri2100/yojson-rs/workflows/CI/badge.svg?branch=master
14//! [source]: https://github.com/puripuri2100/yojson-rs
15//! [source-badge]: https://img.shields.io/badge/source-github-blue
16//! [license]: https://github.com/puripuri2100/yojson-rs/blob/master/LICENSE
17//! [license-badge]: https://img.shields.io/badge/license-MIT-blue
18//!
19//! This library parses [JSON data (yojson format)](https://mjambon.github.io/mjambon2016/yojson.html) into a nested Rust tree data structure.
20//!
21//! # Yojson values
22//!
23//! A value in Yojson is represented with the `Value` enum in this crate:
24//!
25//! ```ignore
26//! pub enum Value {
27//! Null,
28//! Bool(bool),
29//! Integer(i64),
30//! Float(f64),
31//! String(String),
32//! Assoc(Assoc),
33//! Array(Array),
34//! Tuple(Vec<Value>),
35//! Variant(Variant),
36//! }
37//! ```
38//!
39//! The Yojson format is an extension of the JSON format. See ["Yojson format document"](https://mjambon.github.io/mjambon2016/yojson.html) for more information.
40//! - Tuples: like JSON arrays but within parentheses instead of square brackets, such as `(1.23, 4.56)`.
41//! - Variants without argument: `<"Foo">`.
42//! - Variants with one argument: `<"Bar": 123>`.
43//! - Unquoted field names and variants are accepted if they match the pattern `[A-Za-z][A-Za-z_0-9]*`: `{ x: <Foo>, "#y": <Bar2> }`.
44//! - Comments: `/* multiline comment */` and `// end-of-line comment`.
45//! - Special numeric entities: `[ Infinity, -Infinity, NaN ]`.
46//!
47//! # Parsing JSON
48//!
49//! Parse JSON data.
50//!
51//! ```ignore
52//! use yojson_rs;
53//!
54//! # fn main () {
55//! let json = r#"
56//! {
57//! x : 123,
58//! y : {
59//! "y1" : "abc\ndef\u0021",
60//! "y2" : [null, 123.45, (12, "y3")]
61//! },
62//! z : NaN
63//! }
64//! "#;
65//! assert!(yojson_rs::parser::parse(json).is_ok());
66//! # }
67//!
68//! ```
69//!
70//! # Convert to a JSON string.
71//! A data structure can be converted to a JSON string by `to_string`.
72//!
73//! ```ignore
74//! use yojson_rs;
75//!
76//! # fn main() {
77//! let json_str = r#"
78//! {
79//! x : 123,
80//! y : {
81//! "y1" : "abc\ndef\u0021",
82//! "y2" : [null, 123.45, (12, "y3")]
83//! },
84//! z : NaN
85//! }
86//! "#;
87//! let json = yojson_rs::parser::parse(json_str).unwrap();
88//! println!("{}", yojson_rs::to_string(json));
89//! # }
90//! ```
91
92extern crate pest;
93#[macro_use]
94extern crate pest_derive;
95
96pub mod parser;
97pub mod value;
98
99/// Convert to a JSON string.
100pub fn to_string(value: value::Value) -> String {
101 match value {
102 value::Value::Null => "null".to_string(),
103 value::Value::Bool(b) => b.to_string(),
104 value::Value::Integer(i) => i.to_string(),
105 value::Value::Float(f) => f.to_string(),
106 value::Value::String(s) => format!("{:?}", s),
107 value::Value::Assoc(assoc) => {
108 let mut s = String::new();
109 for (i, item) in assoc.iter().enumerate() {
110 let (name, value) = item;
111 if i == 0 {
112 s.push_str(&format!("{}:{}", name, to_string(value.clone())))
113 } else {
114 s.push_str(&format!(",{}:{}", name, to_string(value.clone())))
115 }
116 }
117 format!("{{{}}}", s)
118 }
119 value::Value::Array(array) => {
120 let mut s = String::new();
121 for (i, item) in array.iter().enumerate() {
122 if i == 0 {
123 s.push_str(&to_string(item.clone()))
124 } else {
125 s.push_str(&format!(",{}", to_string(item.clone())))
126 }
127 }
128 format!("[{}]", s)
129 }
130 value::Value::Tuple(tuple) => {
131 let mut s = String::new();
132 for (i, item) in tuple.iter().enumerate() {
133 if i == 0 {
134 s.push_str(&to_string(item.clone()))
135 } else {
136 s.push_str(&format!(",{}", to_string(item.clone())))
137 }
138 }
139 format!("({})", s)
140 }
141 value::Value::Variant(variant) => {
142 let (name, value_opt) = variant;
143 match value_opt {
144 None => format!("<{}>", name),
145 Some(value) => format!("<{}:{}>", name, to_string(*value)),
146 }
147 }
148 }
149}