Strongly-Typed Data Structures
Humphrey JSON provides a powerful way of using Rust data structures to work with JSON data. Mappings between JSON and Rust types can be automatically generated using the FromJson
and IntoJson
derive macro, as well as configured more explicitly using the json_map!
macro.
Deriving FromJson
and IntoJson
The derive macros can only be used when the derive
feature is enabled, which it is by default. The FromJson
and IntoJson
traits can be derived for a type as follows.
use humphrey_json::prelude::*;
#[derive(FromJson, IntoJson)]
struct User {
name: String,
location: String,
}
The macros also support tuple structs and basic enums, but do not yet support enums with variants that have fields. Every type contained within the struct must already implement the traits that are being implemented on the struct.
#[derive(FromJson, IntoJson)]
struct TupleStruct(String, u8);
#[derive(FromJson, IntoJson)]
enum MyEnum {
Yes,
No,
Maybe,
}
Finally, the macros also provide a rename
attribute, which can be used to rename the fields of a struct or the variants of an enum in the JSON data.
#[derive(FromJson, IntoJson)]
struct RenamedFields {
#[rename = "dateOfBirth"]
date_of_birth: String,
}
#[derive(FromJson, IntoJson)]
enum RenamedVariants {
#[rename = "y"]
Yes,
#[rename = "n"]
No,
#[rename = "?"]
Maybe,
}
The json_map!
Macro
The json_map!
macro is used as follows. The fields on the left represent the fields of the struct, and there must be an entry for each field in the struct. The strings on the right represent the names of the fields in the JSON data. It automatically generates a FromJson
and IntoJson
implementation for the struct.
Unlike the derive macros, this macro allows you to specify exactly what names you want to use for each field, instead of just using the struct's field names. On the downside, however, you cannot use the json_map!
macro on enums.
use humphrey_json::prelude::*;
#[derive(PartialEq, Eq)] // not required, but used later in this section
struct User {
name: String,
location: String,
}
json_map! {
User,
name => "name",
location => "country"
}
Parsing into a Struct
To parse a JSON string into a struct, you can simply use the humphrey_json::from_str
function. For example, given the following JSON data, you can parse it into a User
struct as follows:
{
"name": "Humphrey",
"country": "United Kingdom"
}
let user: User = humphrey_json::from_str(json_string).unwrap();
assert_eq!(user, User {
name: "Humphrey".to_string(),
location: "United Kingdom".to_string()
});
This also works for more complex structs, provided that all nested types implement FromJson
.
Serializing into JSON
Instances of any struct which implements IntoJson
can be serialized into JSON, as follows:
let json_string = humphrey_json::to_string(&user).unwrap();
To format the JSON with newlines and to customize the indentation, you can use the to_string_pretty
function, which takes the number of spaces to indent as an argument.
let json_string = humphrey_json::to_string_pretty(&user).unwrap();
Conclusion
In conclusion, the derive macros, the json_map!
macro and their associated functions are a powerful way of working with typed JSON data. To find out more about Humphrey JSON, consider looking at the API reference.