native_json_macro/
lib.rs

1//!# Native JSON for Rust
2//!
3//!This crate provides native JSON syntax for Rust, it brings with a powerful way of parsing JSON syntax into native Rust structs. You can declare the JSON object natively as you do with JavaScript, JSON in Rust was made easy!
4//!
5//!> Note: This crate is just a crude proc-macro (compiler plugin), for more features, please refer to [native-json](https://crates.io/crates/native-json)
6//!
7//!## Usage
8//!Add dependencies to your Cargo.toml, `serde_json` is only needed if you want to stringify the JSON object.
9//!```toml
10//![dependencies]
11//!native-json = "1.2"
12//!serde = {version = "1.0", features = ["derive"] }
13//!serde_json = "1.0"
14//!```
15//!
16//!## Example of using native JSON object
17//!```rust
18//!use native_json::json;
19//!use std::collections::HashMap;
20//!use serde::{Deserialize, Serialize};
21//!
22//!fn main()
23//!{
24//!    let mut json = json!{
25//!        name: "native json",
26//!        style: {
27//!            color: "red",
28//!            size: 12,
29//!            bold: true,
30//!            range: null
31//!        },
32//!        array: [5,4,3,2,1],
33//!        vector: vec![1,2,3,4,5],
34//!        hashmap: HashMap::from([ ("a", 1), ("b", 2), ("c", 3) ]);,
35//!        students: [
36//!            {name: "John", age: 18},
37//!            {name: "Jack", age: 21},
38//!        ],
39//!    };
40//!
41//!    // Native access
42//!    json.style.size += 1;
43//!    json.students[0].age += 2;
44//!
45//!    // Debug
46//!    println!("{:#?}", t);
47//!
48//!    // Stringify
49//!    let text = json.string().unwrap();
50//!    println!("{}", text);
51//!}
52//!```
53//!## Declare a named JSON struct
54//!
55//!With JSON declare syntax, you can declare nested native JSON object in place. 
56//!Note: Identifier with underscore suffix will be renamed when serialize and deserialize, `type_` will be renamed to `type`.
57//!
58//!### JSON Declare Syntax
59//!```rust
60//!json!{
61//!JSON_OBJECT_NAME { 
62//!    name : type, 
63//!    value: type?,  // optional field when serialize & deserialize
64//!    type_: String, // suffix underscore will be removed when serialize & deserialize
65//!    array: [type],
66//!    object: {
67//!        name: type,
68//!        ...
69//!    },
70//!    ...
71//!}}
72//!```
73//!
74//!The native-json will generate native Rust structs for you, each object is named by object hierarchy path, concatenated with underscore.
75//!
76//!  1. `JSON_OBJECT_NAME.object` was converted to `JSON_OBJECT_NAME_object`
77//!  2. `JSON_OBJECT_NAME.array's item` was converted to `JSON_OBJECT_NAME_array_item`
78//!
79//!## Example of using named JSON object
80//!
81//!```rust
82//!use native_json::json;
83//!use serde::{Deserialize, Serialize};
84//!use std::collections::HashMap;
85//!
86//!json!{ 
87//!School {
88//!    name: String,
89//!    rank: u32?, // optional
90//!    students: [
91//!        { name: String, age: u16 },
92//!        ...
93//!    ],
94//!    map: HashMap<String, String>,
95//!    nullable: Option<String>
96//!}}
97//!
98//!fn main()
99//!{
100//!    let mut school = School::new();
101//!
102//!    school.name = "MIT".to_string();
103//!    school.map.insert("Tom".to_owned(), "Profile".to_owned());
104//!
105//!    // using initializer
106//!    let mut john = School_students_item::new();
107//!    john.name = "John".to_owned();
108//!    john.age = 18;
109//!    school.students.push(john);
110//!
111//!    // using struct
112//!    let jack = School_students_item { name: "Jack".to_string(), age: 21 };
113//!    school.students.push(jack);
114//!
115//!    // show
116//!    println!("{:#?}", school);
117//!}
118//!```
119//!
120extern crate proc_macro;
121mod json;
122
123use json::*;
124use proc_macro::TokenStream;
125use std::str::FromStr;
126use syn::parse_macro_input;
127
128/// Declare or instantiate a native JSON object, please refere to module [json](index.html)
129#[proc_macro]
130pub fn json(input: TokenStream) -> TokenStream {
131    let parser = parse_macro_input!(input as Json);
132    let block = parser.get_block();
133    // Show me the code
134    // println!("XXXXXXXXXXXXXXXX\n{}", block);
135    return TokenStream::from_str(block.as_str()).unwrap();
136}