diff --git a/Cargo.lock b/Cargo.lock index 4def7fff..a876e59c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -955,6 +955,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ + "indexmap", "itoa", "memchr", "serde", diff --git a/README.md b/README.md index 7c9d516d..891be82f 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,11 @@ applied. Non-required properties with types that already have a default value (such as a `Vec`) simply get the `#[serde(default)]` attribute (so you won't see e.g. `Option>`). +By default, properties are ordered by their original name. +The feature `preserve_order` may be used to keep the order as set in the given schema. +To ensure deserializing a schema using `serde_json` does not change the order of properties, +set the `preserve_order` feature of `serde_json`. + #### Alternate Map types By default, Typify uses `std::collections::HashMap` as described above. diff --git a/typify-impl/Cargo.toml b/typify-impl/Cargo.toml index 36b72134..fa3ddcb9 100644 --- a/typify-impl/Cargo.toml +++ b/typify-impl/Cargo.toml @@ -7,6 +7,9 @@ description = "typify backend implementation" repository = "https://github.com/oxidecomputer/typify" readme = "../README.md" +[features] +preserve_order = [] + [dependencies] heck = { workspace = true } log = { workspace = true } diff --git a/typify-impl/src/structs.rs b/typify-impl/src/structs.rs index 379c34c9..d452fd93 100644 --- a/typify-impl/src/structs.rs +++ b/typify-impl/src/structs.rs @@ -71,7 +71,20 @@ impl TypeSpace { .collect::>>()?; // Sort parameters by name to ensure a deterministic result. - properties.sort_by(|a, b| a.name.cmp(&b.name)); + #[cfg(not(feature = "preserve_order"))] + properties.sort_by(|a, b| { + let a_name = match &a.rename { + StructPropertyRename::Rename(a_rename) => a_rename, + _ => &a.name, + }; + + let b_name = match &b.rename { + StructPropertyRename::Rename(b_rename) => b_rename, + _ => &b.name, + }; + + a_name.cmp(b_name) + }); // If there are additional properties tack them on, flattened, at the // end. Note that a `None` value for additional_properties is diff --git a/typify-impl/tests/github.out b/typify-impl/tests/github.out index 53d82841..b43de945 100644 --- a/typify-impl/tests/github.out +++ b/typify-impl/tests/github.out @@ -26891,6 +26891,8 @@ impl ::std::convert::From<::chrono::DateTime<::chrono::offset::Utc>> #[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)] #[serde(deny_unknown_fields)] pub struct PullRequest { + #[serde(rename = "_links")] + pub links: PullRequestLinks, #[serde(deserialize_with = "::std::option::Option::deserialize")] pub active_lock_reason: ::std::option::Option, pub additions: i64, @@ -26919,8 +26921,6 @@ pub struct PullRequest { pub id: i64, pub issue_url: ::std::string::String, pub labels: ::std::vec::Vec