From 6cead069d95e5e863bef38644f5fa88bfbe18078 Mon Sep 17 00:00:00 2001 From: Manuel Hatzl Date: Thu, 8 Oct 2026 15:07:13 +0200 Subject: [PATCH 1/4] Sort obj props by original name or keep order unchanged Feature name 'preserve_order' used to stay consistent with `serde_json`. --- typify-impl/Cargo.toml | 3 +++ typify-impl/src/structs.rs | 15 ++++++++++++++- typify/Cargo.toml | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) 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/Cargo.toml b/typify/Cargo.toml index 7315bbe2..96c376be 100644 --- a/typify/Cargo.toml +++ b/typify/Cargo.toml @@ -12,6 +12,7 @@ categories = ["api-bindings", "compilers"] [features] default = ["macro"] macro = ["typify-macro"] +preserve_order = ["typify-impl/preserve_order"] [dependencies] typify-macro = { workspace = true, optional = true } From 0726662b51baad3e7cba031ffba98376cbf199cc Mon Sep 17 00:00:00 2001 From: Manuel Hatzl Date: Thu, 8 Oct 2026 15:20:32 +0200 Subject: [PATCH 2/4] Set preserve_order for serde_json if flag set for typify --- Cargo.lock | 1 + typify/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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/typify/Cargo.toml b/typify/Cargo.toml index 96c376be..4b92d809 100644 --- a/typify/Cargo.toml +++ b/typify/Cargo.toml @@ -12,7 +12,7 @@ categories = ["api-bindings", "compilers"] [features] default = ["macro"] macro = ["typify-macro"] -preserve_order = ["typify-impl/preserve_order"] +preserve_order = ["typify-impl/preserve_order", "serde_json/preserve_order"] [dependencies] typify-macro = { workspace = true, optional = true } From 86d73fe6fa89a96738401bd42d7924aac30f0a80 Mon Sep 17 00:00:00 2001 From: Manuel Hatzl Date: Thu, 8 Oct 2026 15:21:07 +0200 Subject: [PATCH 3/4] Document how property ordering is done --- README.md | 5 +++++ 1 file changed, 5 insertions(+) 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. From 6938a99712914ca71b1fe48164690b0e56e29aae Mon Sep 17 00:00:00 2001 From: Manuel Hatzl Date: Thu, 8 Oct 2026 15:24:06 +0200 Subject: [PATCH 4/4] Fix property orders in expected test results --- typify-impl/tests/github.out | 56 ++++++++++++++++++------------------ typify-impl/tests/vega.out | 10 +++---- 2 files changed, 33 insertions(+), 33 deletions(-) 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