]>
Commit | Line | Data |
---|---|---|
1 | # Serde JSON   [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.15+]][rustc] | |
2 | ||
3 | [Build Status]: https://api.travis-ci.org/serde-rs/json.svg?branch=master | |
4 | [travis]: https://travis-ci.org/serde-rs/json | |
5 | [Latest Version]: https://img.shields.io/crates/v/serde_json.svg | |
6 | [crates.io]: https://crates.io/crates/serde\_json | |
7 | [Rustc Version 1.15+]: https://img.shields.io/badge/rustc-1.15+-lightgray.svg | |
8 | [rustc]: https://blog.rust-lang.org/2017/02/02/Rust-1.15.html | |
9 | ||
10 | **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** | |
11 | ||
12 | --- | |
13 | ||
14 | ```toml | |
15 | [dependencies] | |
16 | serde_json = "1.0" | |
17 | ``` | |
18 | ||
19 | You may be looking for: | |
20 | ||
21 | - [JSON API documentation](https://docs.serde.rs/serde_json/) | |
22 | - [Serde API documentation](https://docs.serde.rs/serde/) | |
23 | - [Detailed documentation about Serde](https://serde.rs/) | |
24 | - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html) | |
25 | - [Release notes](https://github.com/serde-rs/json/releases) | |
26 | ||
27 | JSON is a ubiquitous open-standard format that uses human-readable text to | |
28 | transmit data objects consisting of key-value pairs. | |
29 | ||
30 | ```json,ignore | |
31 | { | |
32 | "name": "John Doe", | |
33 | "age": 43, | |
34 | "address": { | |
35 | "street": "10 Downing Street", | |
36 | "city": "London" | |
37 | }, | |
38 | "phones": [ | |
39 | "+44 1234567", | |
40 | "+44 2345678" | |
41 | ] | |
42 | } | |
43 | ``` | |
44 | ||
45 | There are three common ways that you might find yourself needing to work | |
46 | with JSON data in Rust. | |
47 | ||
48 | - **As text data.** An unprocessed string of JSON data that you receive on | |
49 | an HTTP endpoint, read from a file, or prepare to send to a remote | |
50 | server. | |
51 | - **As an untyped or loosely typed representation.** Maybe you want to | |
52 | check that some JSON data is valid before passing it on, but without | |
53 | knowing the structure of what it contains. Or you want to do very basic | |
54 | manipulations like insert a key in a particular spot. | |
55 | - **As a strongly typed Rust data structure.** When you expect all or most | |
56 | of your data to conform to a particular structure and want to get real | |
57 | work done without JSON's loosey-goosey nature tripping you up. | |
58 | ||
59 | Serde JSON provides efficient, flexible, safe ways of converting data | |
60 | between each of these representations. | |
61 | ||
62 | ## Operating on untyped JSON values | |
63 | ||
64 | Any valid JSON data can be manipulated in the following recursive enum | |
65 | representation. This data structure is [`serde_json::Value`][value]. | |
66 | ||
67 | ```rust,ignore | |
68 | enum Value { | |
69 | Null, | |
70 | Bool(bool), | |
71 | Number(Number), | |
72 | String(String), | |
73 | Array(Vec<Value>), | |
74 | Object(Map<String, Value>), | |
75 | } | |
76 | ``` | |
77 | ||
78 | A string of JSON data can be parsed into a `serde_json::Value` by the | |
79 | [`serde_json::from_str`][from_str] function. There is also | |
80 | [`from_slice`][from_slice] for parsing from a byte slice &[u8] and | |
81 | [`from_reader`][from_reader] for parsing from any `io::Read` like a File or | |
82 | a TCP stream. | |
83 | ||
84 | <a href="http://play.integer32.com/?gist=a266662bc71712e080efbf25ce30f306" target="_blank"> | |
85 | <img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png"> | |
86 | </a> | |
87 | ||
88 | ```rust | |
89 | extern crate serde_json; | |
90 | ||
91 | use serde_json::{Value, Error}; | |
92 | ||
93 | fn untyped_example() -> Result<(), Error> { | |
94 | // Some JSON input data as a &str. Maybe this comes from the user. | |
95 | let data = r#"{ | |
96 | "name": "John Doe", | |
97 | "age": 43, | |
98 | "phones": [ | |
99 | "+44 1234567", | |
100 | "+44 2345678" | |
101 | ] | |
102 | }"#; | |
103 | ||
104 | // Parse the string of data into serde_json::Value. | |
105 | let v: Value = serde_json::from_str(data)?; | |
106 | ||
107 | // Access parts of the data by indexing with square brackets. | |
108 | println!("Please call {} at the number {}", v["name"], v["phones"][0]); | |
109 | ||
110 | Ok(()) | |
111 | } | |
112 | ``` | |
113 | ||
114 | The result of square bracket indexing like `v["name"]` is a borrow of the data | |
115 | at that index, so the type is `&Value`. A JSON map can be indexed with string | |
116 | keys, while a JSON array can be indexed with integer keys. If the type of the | |
117 | data is not right for the type with which it is being indexed, or if a map does | |
118 | not contain the key being indexed, or if the index into a vector is out of | |
119 | bounds, the returned element is `Value::Null`. | |
120 | ||
121 | When a `Value` is printed, it is printed as a JSON string. So in the code above, | |
122 | the output looks like `Please call "John Doe" at the number "+44 1234567"`. The | |
123 | quotation marks appear because `v["name"]` is a `&Value` containing a JSON | |
124 | string and its JSON representation is `"John Doe"`. Printing as a plain string | |
125 | without quotation marks involves converting from a JSON string to a Rust string | |
126 | with [`as_str()`] or avoiding the use of `Value` as described in the following | |
127 | section. | |
128 | ||
129 | [`as_str()`]: https://docs.serde.rs/serde_json/enum.Value.html#method.as_str | |
130 | ||
131 | The `Value` representation is sufficient for very basic tasks but can be tedious | |
132 | to work with for anything more significant. Error handling is verbose to | |
133 | implement correctly, for example imagine trying to detect the presence of | |
134 | unrecognized fields in the input data. The compiler is powerless to help you | |
135 | when you make a mistake, for example imagine typoing `v["name"]` as `v["nmae"]` | |
136 | in one of the dozens of places it is used in your code. | |
137 | ||
138 | ## Parsing JSON as strongly typed data structures | |
139 | ||
140 | Serde provides a powerful way of mapping JSON data into Rust data structures | |
141 | largely automatically. | |
142 | ||
143 | <a href="http://play.integer32.com/?gist=cff572b80d3f078c942a2151e6020adc" target="_blank"> | |
144 | <img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png"> | |
145 | </a> | |
146 | ||
147 | ```rust | |
148 | extern crate serde; | |
149 | extern crate serde_json; | |
150 | ||
151 | #[macro_use] | |
152 | extern crate serde_derive; | |
153 | ||
154 | use serde_json::Error; | |
155 | ||
156 | #[derive(Serialize, Deserialize)] | |
157 | struct Person { | |
158 | name: String, | |
159 | age: u8, | |
160 | phones: Vec<String>, | |
161 | } | |
162 | ||
163 | fn typed_example() -> Result<(), Error> { | |
164 | // Some JSON input data as a &str. Maybe this comes from the user. | |
165 | let data = r#"{ | |
166 | "name": "John Doe", | |
167 | "age": 43, | |
168 | "phones": [ | |
169 | "+44 1234567", | |
170 | "+44 2345678" | |
171 | ] | |
172 | }"#; | |
173 | ||
174 | // Parse the string of data into a Person object. This is exactly the | |
175 | // same function as the one that produced serde_json::Value above, but | |
176 | // now we are asking it for a Person as output. | |
177 | let p: Person = serde_json::from_str(data)?; | |
178 | ||
179 | // Do things just like with any other Rust data structure. | |
180 | println!("Please call {} at the number {}", p.name, p.phones[0]); | |
181 | ||
182 | Ok(()) | |
183 | } | |
184 | ``` | |
185 | ||
186 | This is the same `serde_json::from_str` function as before, but this time we | |
187 | assign the return value to a variable of type `Person` so Serde will | |
188 | automatically interpret the input data as a `Person` and produce informative | |
189 | error messages if the layout does not conform to what a `Person` is expected | |
190 | to look like. | |
191 | ||
192 | Any type that implements Serde's `Deserialize` trait can be deserialized | |
193 | this way. This includes built-in Rust standard library types like `Vec<T>` | |
194 | and `HashMap<K, V>`, as well as any structs or enums annotated with | |
195 | `#[derive(Deserialize)]`. | |
196 | ||
197 | Once we have `p` of type `Person`, our IDE and the Rust compiler can help us | |
198 | use it correctly like they do for any other Rust code. The IDE can | |
199 | autocomplete field names to prevent typos, which was impossible in the | |
200 | `serde_json::Value` representation. And the Rust compiler can check that | |
201 | when we write `p.phones[0]`, then `p.phones` is guaranteed to be a | |
202 | `Vec<String>` so indexing into it makes sense and produces a `String`. | |
203 | ||
204 | ## Constructing JSON values | |
205 | ||
206 | Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value` | |
207 | objects with very natural JSON syntax. In order to use this macro, | |
208 | `serde_json` needs to be imported with the `#[macro_use]` attribute. | |
209 | ||
210 | <a href="http://play.integer32.com/?gist=c216d6beabd9429a6ac13b8f88938dfe" target="_blank"> | |
211 | <img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png"> | |
212 | </a> | |
213 | ||
214 | ```rust | |
215 | #[macro_use] | |
216 | extern crate serde_json; | |
217 | ||
218 | fn main() { | |
219 | // The type of `john` is `serde_json::Value` | |
220 | let john = json!({ | |
221 | "name": "John Doe", | |
222 | "age": 43, | |
223 | "phones": [ | |
224 | "+44 1234567", | |
225 | "+44 2345678" | |
226 | ] | |
227 | }); | |
228 | ||
229 | println!("first phone number: {}", john["phones"][0]); | |
230 | ||
231 | // Convert to a string of JSON and print it out | |
232 | println!("{}", john.to_string()); | |
233 | } | |
234 | ``` | |
235 | ||
236 | The `Value::to_string()` function converts a `serde_json::Value` into a | |
237 | `String` of JSON text. | |
238 | ||
239 | One neat thing about the `json!` macro is that variables and expressions can | |
240 | be interpolated directly into the JSON value as you are building it. Serde | |
241 | will check at compile time that the value you are interpolating is able to | |
242 | be represented as JSON. | |
243 | ||
244 | <a href="http://play.integer32.com/?gist=aae3af4d274bd249d1c8a947076355f2" target="_blank"> | |
245 | <img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png"> | |
246 | </a> | |
247 | ||
248 | ```rust | |
249 | let full_name = "John Doe"; | |
250 | let age_last_year = 42; | |
251 | ||
252 | // The type of `john` is `serde_json::Value` | |
253 | let john = json!({ | |
254 | "name": full_name, | |
255 | "age": age_last_year + 1, | |
256 | "phones": [ | |
257 | format!("+44 {}", random_phone()) | |
258 | ] | |
259 | }); | |
260 | ``` | |
261 | ||
262 | This is amazingly convenient but we have the problem we had before with | |
263 | `Value` which is that the IDE and Rust compiler cannot help us if we get it | |
264 | wrong. Serde JSON provides a better way of serializing strongly-typed data | |
265 | structures into JSON text. | |
266 | ||
267 | ## Creating JSON by serializing data structures | |
268 | ||
269 | A data structure can be converted to a JSON string by | |
270 | [`serde_json::to_string`][to_string]. There is also | |
271 | [`serde_json::to_vec`][to_vec] which serializes to a `Vec<u8>` and | |
272 | [`serde_json::to_writer`][to_writer] which serializes to any `io::Write` | |
273 | such as a File or a TCP stream. | |
274 | ||
275 | <a href="http://play.integer32.com/?gist=40967ece79921c77fd78ebc8f177c063" target="_blank"> | |
276 | <img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png"> | |
277 | </a> | |
278 | ||
279 | ```rust | |
280 | extern crate serde; | |
281 | extern crate serde_json; | |
282 | ||
283 | #[macro_use] | |
284 | extern crate serde_derive; | |
285 | ||
286 | use serde_json::Error; | |
287 | ||
288 | #[derive(Serialize, Deserialize)] | |
289 | struct Address { | |
290 | street: String, | |
291 | city: String, | |
292 | } | |
293 | ||
294 | fn print_an_address() -> Result<(), Error> { | |
295 | // Some data structure. | |
296 | let address = Address { | |
297 | street: "10 Downing Street".to_owned(), | |
298 | city: "London".to_owned(), | |
299 | }; | |
300 | ||
301 | // Serialize it to a JSON string. | |
302 | let j = serde_json::to_string(&address)?; | |
303 | ||
304 | // Print, write to a file, or send to an HTTP server. | |
305 | println!("{}", j); | |
306 | ||
307 | Ok(()) | |
308 | } | |
309 | ``` | |
310 | ||
311 | Any type that implements Serde's `Serialize` trait can be serialized this | |
312 | way. This includes built-in Rust standard library types like `Vec<T>` and | |
313 | `HashMap<K, V>`, as well as any structs or enums annotated with | |
314 | `#[derive(Serialize)]`. | |
315 | ||
316 | ## Performance | |
317 | ||
318 | It is fast. You should expect in the ballpark of 500 to 1000 megabytes per | |
319 | second deserialization and 600 to 900 megabytes per second serialization, | |
320 | depending on the characteristics of your data. This is competitive with the | |
321 | fastest C and C++ JSON libraries or even 30% faster for many use cases. | |
322 | Benchmarks live in the [serde-rs/json-benchmark] repo. | |
323 | ||
324 | [serde-rs/json-benchmark]: https://github.com/serde-rs/json-benchmark | |
325 | ||
326 | ## Getting help | |
327 | ||
328 | Serde developers live in the #serde channel on | |
329 | [`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a | |
330 | good resource with generally faster response time but less specific knowledge | |
331 | about Serde. If IRC is not your thing, we are happy to respond to [GitHub | |
332 | issues](https://github.com/serde-rs/json/issues/new) as well. | |
333 | ||
334 | ## No-std support | |
335 | ||
336 | This crate currently requires the Rust standard library. For JSON support in | |
337 | Serde without a standard library, please see the [`serde-json-core`] crate. | |
338 | ||
339 | [`serde-json-core`]: https://japaric.github.io/serde-json-core/serde_json_core/ | |
340 | ||
341 | ## License | |
342 | ||
343 | Serde JSON is licensed under either of | |
344 | ||
345 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or | |
346 | http://www.apache.org/licenses/LICENSE-2.0) | |
347 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or | |
348 | http://opensource.org/licenses/MIT) | |
349 | ||
350 | at your option. | |
351 | ||
352 | ### Contribution | |
353 | ||
354 | Unless you explicitly state otherwise, any contribution intentionally submitted | |
355 | for inclusion in Serde JSON by you, as defined in the Apache-2.0 license, shall | |
356 | be dual licensed as above, without any additional terms or conditions. | |
357 | ||
358 | [value]: https://docs.serde.rs/serde_json/value/enum.Value.html | |
359 | [from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html | |
360 | [from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html | |
361 | [from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html | |
362 | [to_string]: https://docs.serde.rs/serde_json/ser/fn.to_string.html | |
363 | [to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html | |
364 | [to_writer]: https://docs.serde.rs/serde_json/ser/fn.to_writer.html | |
365 | [macro]: https://docs.serde.rs/serde_json/macro.json.html |