27 releases (13 stable)

2.2.4 Nov 28, 2023
2.2.1 Oct 27, 2023
2.0.0 Jul 9, 2023
1.2.0 May 25, 2023
0.1.4 Dec 21, 2020

#55 in Encoding

Download history 5353/week @ 2024-08-12 4517/week @ 2024-08-19 4536/week @ 2024-08-26 4269/week @ 2024-09-02 2978/week @ 2024-09-09 3645/week @ 2024-09-16 3848/week @ 2024-09-23 5582/week @ 2024-09-30 5037/week @ 2024-10-07 5683/week @ 2024-10-14 6534/week @ 2024-10-21 7346/week @ 2024-10-28 7514/week @ 2024-11-04 8134/week @ 2024-11-11 9034/week @ 2024-11-18 6590/week @ 2024-11-25

31,480 downloads per month
Used in 30 crates (16 directly)

MIT license

51KB
1K SLoC

MIT Latest Version docs Chat on Miaou

deser_hjson

This is a Serde deserializer for Hjson, tailored for derive powered deserialization.

Hjson is a good language for a configuration file. Such files should be written by a human, read and modified by other humans, then deserialized into a precise structure by a program:

let file_content = fs::read_to_string(&file_path)?;
let configuration = deser_hjson::from_str(&file_content);

If the configuration file is invalid or doesn't match the expected type, the error details the expectation and the error precise location.

Example

use {
    deser_hjson::*,
    serde::Deserialize,
    std::collections::HashMap,
};
// This Hjson document comes from https://hjson.github.io/
let hjson = r#"
// use #, // or /**/ for comments,
// omit quotes for keys
key: 1
// omit quotes for strings
contains: everything on this line
// omit commas at the end of a line
cool: {
  foo: 1
  bar: 2
}
// allow trailing commas
list: [
  1,
  2,
]
// and use multiline strings
realist:
  '''
  My half empty glass,
  I will fill your empty half.
  Now you are half full.
  '''
"#;
// we'll deserialize it into this struct:
#[derive(Deserialize, PartialEq, Debug)]
struct Example {
    key: i32,
    contains: Option<String>,
    cool: HashMap<String, u16>,
    list: Vec<usize>,
    realist: String,
    missing: Option<f64>,
}
let mut cool = HashMap::new();
cool.insert("foo".to_owned(), 1);
cool.insert("bar".to_owned(), 2);
let expected = Example {
    key: 1,
    contains: Some("everything on this line".to_owned()),
    cool,
    list: vec![1, 2],
    realist: "My half empty glass,\nI will fill your empty half.\nNow you are half full.".to_owned(),
    missing: None,
};
// Here's the deserialization and the equality check:
assert_eq!(expected, from_str(hjson).unwrap());

Known open-source usages

  • Broot can be configured either with TOML or with Hjson (the selection is dynamic, based on the file extension).

  • lemmy is configured in Hjson

  • Resc can be configured either with JSON or with Hjson

FAQ

Does it work with JSON ?

Yes as any JSON file can be read as Hjson.

Why only a derive-based deserializer?

Guessing the types in a format with implicit typing is way too dangereous. When your user typed false, was it a string or a boolean ? When she typed 3, was it as string or a number ? While not as crazy as YAML, Hjson has no internal guard for this, and thus should only be deserialized into explicit types.

Why a deserializer and no serializer?

Hjson isn't a data exchange format. It's intended to be written by humans, be full of comments and with a meaningful formatting. While serializers would make sense in some context, they would have to be template based, or offer other means to specify comments and formatting, and serde isn't the right tool for that.

Dependencies

~0.3–1MB
~21K SLoC