Expand description
A serde-enabled implementation of the JSONX format.
JSONX is a superset of JSON that relaxes the syntax and adds a handful of typed value constructors. Concretely, on top of JSON it supports:
- Unquoted object keys matching
^[A-Za-z_][0-9A-Za-z_]*$. - Trailing commas after the last array/object element.
- Typed constructors written as
type(value):- sized integers:
int8,int16,int32,int64,uint8,uint16,uint32,uint64, and the machine-widthint/uint; datetime("2017-12-25T15:00:00Z")(RFC 3339);ip("192.168.1.2")/ip("::1");ipport("192.168.1.2:65000")/ipport("[::1]:65000");bytes("YWJjZA==")(standard Base64).
- sized integers:
Plain JSON numbers always decode to an f64, exactly as in the reference
implementation; the constructors above are how you get a typed integer or
one of the extended types.
§Quick start
Work with arbitrary documents via Value:
let value: jsonx::Value = jsonx::from_str("{ id: int(7), tags: [\"a\", \"b\",] }").unwrap();
assert_eq!(value.get("id"), Some(&jsonx::Value::Int(7)));
let text = jsonx::to_string(&value).unwrap();
assert_eq!(text, r#"{id:int(7),tags:["a","b"]}"#);Or derive Serialize/Deserialize on your own types. Rust integer types
map to the matching JSONX sized integers, and plain f64s stay bare:
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
struct Server {
name: String,
port: u16,
weight: i32,
}
let server = Server { name: "db".into(), port: 5432, weight: -1 };
let text = jsonx::to_string(&server).unwrap();
assert_eq!(text, r#"{name:"db",port:uint16(5432),weight:int32(-1)}"#);
assert_eq!(jsonx::from_str::<Server>(&text).unwrap(), server);§Extended types
For the non-integer extended types, the most ergonomic option is the wrapper
types in this crate — Bytes, Int, Uint, Ip, IpPort, and
Datetime. They need no attribute, and because they stay transparent in
other serde formats, the same struct also serializes cleanly to (say) TOML
or JSON, where they degrade to plain strings/integers:
use jsonx::{Ip, Datetime, DateTime};
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
struct Peer {
addr: Ip,
seen: Datetime,
}
let peer = Peer {
addr: Ip("10.0.0.1".parse().unwrap()),
seen: Datetime(DateTime::parse_from_rfc3339("2024-06-01T09:00:00Z").unwrap()),
};
let text = jsonx::to_string(&peer).unwrap();
assert_eq!(text, r#"{addr:ip("10.0.0.1"),seen:datetime("2024-06-01T09:00:00Z")}"#);If you must keep a bare std::net address or DateTime field, the
ip, ipport, and datetime modules provide #[serde(with = ...)]
glue instead.
§Extending JSONX with your own constructors
JSONX is open: you can teach it a type(value) constructor for one of your
own types by implementing JsonxConstructor. See the constructor
module for the details.
§Non-greedy decoding
from_str_partial decodes a single value and tells you where it stopped,
so you can parse a stream of concatenated values.
Re-exports§
pub use constructor::deserialize_constructor;pub use constructor::serialize_constructor;pub use constructor::JsonxConstructor;pub use datetime::DateTime;pub use error::Error;pub use error::Result;
Modules§
- constructor
- Open extension API: render your own types as JSONX
name(value)constructors. - datetime
- RFC 3339 date-time support for the
datetime(...)type, backed bychrono. - error
- Error and result types for
jsonx. - ip
- (De)serializes an
IpAddrfield as JSONXip("..."). - ipport
- (De)serializes a
SocketAddrfield as JSONXipport("...").
Macros§
- ctor
- Encodes a constructor
nameinto the&'static strtoken the jsonx serializer recognizes. Use it to setJsonxConstructor::TOKEN.
Structs§
- Bytes
- Wraps a byte buffer so it (de)serializes as
bytes("...")(Base64). - Datetime
- Wraps a
DateTimeso it (de)serializes as JSONXdatetime("...")with no attribute, and as a plain RFC 3339 string in other formats. - Deserializer
- A JSONX deserializer over a byte slice. Strings borrow from the input when they contain no escapes.
- Int
- Wraps an
i64so it serializes asint(...)(the machine-width signed integer). It deserializes from any JSONX integer form. - Ip
- Wraps an
IpAddrso it (de)serializes as JSONXip("...")with no#[serde(with = ...)]attribute. Other serde formats see a transparent newtype, so it stays a plain string there (e.g."10.0.0.1"in TOML/JSON). - IpPort
- Wraps a
SocketAddrso it (de)serializes as JSONXipport("...")with no attribute, and as a plain string in other formats. TheIpPortanalogue ofIp; seeipportfor the bare-SocketAddralternative. - Serializer
- A JSONX serializer writing to an
io::Write. - Uint
- Wraps a
u64so it serializes asuint(...)(the machine-width unsigned integer). It deserializes from any non-negative JSONX integer form.
Enums§
- Value
- A dynamically-typed JSONX value.
Functions§
- from_
slice - Deserializes a
Tfrom JSONX bytes, requiring that the entire input is consumed (only trailing whitespace is allowed). - from_
str - Deserializes a
Tfrom a JSONX string, requiring that the entire input is consumed (only trailing whitespace is allowed). - from_
str_ partial - Non-greedy decoding: deserializes a single top-level value and returns it together with the byte offset of the first byte that was not consumed (after skipping trailing whitespace). The offset equals the input length when nothing follows the value.
- to_
string - Serializes a value to a compact JSONX
String. - to_
string_ indent - Serializes a value to pretty-printed JSONX with a custom line
prefixand per-levelindent. - to_
string_ pretty - Serializes a value to pretty-printed JSONX using a two-space indent.
- to_vec
- Serializes a value to a compact JSONX byte vector.
- to_
writer - Serializes a value as compact JSONX to an
io::Write. - to_
writer_ pretty - Serializes a value as pretty JSONX (two-space indent) to an
io::Write.
Type Aliases§
- Map
- A JSONX object.
Derive Macros§
- Jsonx
Constructor - Derives
JsonxConstructorplus the serde impls that wire it in, for a type that implementsDisplayandFromStr.