diff --git a/Cargo.lock b/Cargo.lock index 730334dad3..ae2dd9761a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -325,6 +325,7 @@ dependencies = [ "quickcheck_macros", "reqwest", "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -393,6 +394,7 @@ dependencies = [ "reqwest", "rustversion", "serde", + "serde_core", "serde_html_form", "serde_json", "serde_path_to_error", @@ -2842,7 +2844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -4164,10 +4166,11 @@ checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.221" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "341877e04a22458705eb4e131a1508483c877dca2792b3781d4e5d8a6019ec43" dependencies = [ + "serde_core", "serde_derive", ] @@ -4180,11 +4183,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.221" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c459bc0a14c840cb403fc14b148620de1e0778c96ecd6e0c8c3cacb6d8d00fe" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.221" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "d6185cf75117e20e62b1ff867b9518577271e58abe0037c40bb4794969355ab0" dependencies = [ "proc-macro2", "quote", diff --git a/axum-extra/Cargo.toml b/axum-extra/Cargo.toml index 0968d0285d..bdb5fc6ba4 100644 --- a/axum-extra/Cargo.toml +++ b/axum-extra/Cargo.toml @@ -29,7 +29,7 @@ allowed = [ "http_body", "pin_project_lite", "prost", - "serde", + "serde_core", "tokio", "tokio_util", "tower_layer", @@ -78,10 +78,8 @@ typed-routing = [ ] # Enabled by docs.rs because it uses all-features -__private_docs = [ - # Required for the ErasedJson docs to be able to link to axum::Json - "axum/json", -] +# Enables upstream things linked to in docs +__private_docs = ["axum/json", "dep:serde"] [dependencies] axum = { path = "../axum", version = "0.8.4", default-features = false, features = ["original-uri"] } @@ -95,7 +93,7 @@ http-body-util = "0.1.0" mime = "0.3" pin-project-lite = "0.2" rustversion = "1.0.9" -serde = "1.0" +serde_core = "1.0.221" tower = { version = "0.5.2", default-features = false, features = ["util"] } tower-layer = "0.3" tower-service = "0.3" @@ -118,12 +116,15 @@ tokio-util = { version = "0.7", optional = true } tracing = { version = "0.1.37", default-features = false, optional = true } typed-json = { version = "0.1.1", optional = true } +# doc dependencies +serde = { version = "1.0.221", optional = true } + [dev-dependencies] axum = { path = "../axum", features = ["macros", "__private"] } axum-macros = { path = "../axum-macros", features = ["__private"] } hyper = "1.0.0" reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] } -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.221", features = ["derive"] } serde_json = "1.0.71" tokio = { version = "1.14", features = ["full"] } tower = { version = "0.5.2", features = ["util"] } diff --git a/axum-extra/src/extract/form.rs b/axum-extra/src/extract/form.rs index 454c50a727..717d0a189a 100644 --- a/axum-extra/src/extract/form.rs +++ b/axum-extra/src/extract/form.rs @@ -5,7 +5,7 @@ use axum::{ }; use axum_core::__composite_rejection as composite_rejection; use axum_core::__define_rejection as define_rejection; -use serde::de::DeserializeOwned; +use serde_core::de::DeserializeOwned; /// Extractor that deserializes `application/x-www-form-urlencoded` requests /// into some type. diff --git a/axum-extra/src/extract/json_deserializer.rs b/axum-extra/src/extract/json_deserializer.rs index 8d53101999..2d1208f9cd 100644 --- a/axum-extra/src/extract/json_deserializer.rs +++ b/axum-extra/src/extract/json_deserializer.rs @@ -4,7 +4,7 @@ use axum_core::__define_rejection as define_rejection; use axum_core::extract::rejection::BytesRejection; use bytes::Bytes; use http::{header, HeaderMap}; -use serde::Deserialize; +use serde_core::Deserialize; use std::marker::PhantomData; /// JSON Extractor for zero-copy deserialization. diff --git a/axum-extra/src/extract/optional_path.rs b/axum-extra/src/extract/optional_path.rs index 466944ff55..2b4cd6d586 100644 --- a/axum-extra/src/extract/optional_path.rs +++ b/axum-extra/src/extract/optional_path.rs @@ -2,7 +2,7 @@ use axum::{ extract::{rejection::PathRejection, FromRequestParts, Path}, RequestPartsExt, }; -use serde::de::DeserializeOwned; +use serde_core::de::DeserializeOwned; /// Extractor that extracts path arguments the same way as [`Path`], except if there aren't any. /// diff --git a/axum-extra/src/extract/query.rs b/axum-extra/src/extract/query.rs index db16461b2f..c2caf03c06 100644 --- a/axum-extra/src/extract/query.rs +++ b/axum-extra/src/extract/query.rs @@ -2,7 +2,7 @@ use axum::extract::FromRequestParts; use axum_core::__composite_rejection as composite_rejection; use axum_core::__define_rejection as define_rejection; use http::{request::Parts, Uri}; -use serde::de::DeserializeOwned; +use serde_core::de::DeserializeOwned; /// Extractor that deserializes query strings into some type. /// diff --git a/axum-extra/src/json_lines.rs b/axum-extra/src/json_lines.rs index 9aea94dc83..0b52af727d 100644 --- a/axum-extra/src/json_lines.rs +++ b/axum-extra/src/json_lines.rs @@ -10,7 +10,7 @@ use bytes::{BufMut, BytesMut}; use futures_core::{stream::BoxStream, Stream, TryStream}; use futures_util::stream::TryStreamExt; use pin_project_lite::pin_project; -use serde::{de::DeserializeOwned, Serialize}; +use serde_core::{de::DeserializeOwned, Serialize}; use std::{ convert::Infallible, io::{self, Write}, @@ -174,7 +174,7 @@ where #[cfg(test)] mod tests { - use super::*; + use super::JsonLines; use crate::test_helpers::*; use axum::{ routing::{get, post}, @@ -182,8 +182,8 @@ mod tests { }; use futures_util::StreamExt; use http::StatusCode; - use serde::Deserialize; - use std::error::Error; + use serde::{Deserialize, Serialize}; + use std::{convert::Infallible, error::Error}; #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] struct User { diff --git a/axum-extra/src/response/erased_json.rs b/axum-extra/src/response/erased_json.rs index 5088ff35fb..de0fc2213e 100644 --- a/axum-extra/src/response/erased_json.rs +++ b/axum-extra/src/response/erased_json.rs @@ -5,7 +5,7 @@ use axum::{ response::{IntoResponse, Response}, }; use bytes::{BufMut, Bytes, BytesMut}; -use serde::Serialize; +use serde_core::Serialize; /// A response type that holds a JSON in serialized form. /// diff --git a/axum-extra/src/routing/typed.rs b/axum-extra/src/routing/typed.rs index eccdfb19de..f45ef05381 100644 --- a/axum-extra/src/routing/typed.rs +++ b/axum-extra/src/routing/typed.rs @@ -2,7 +2,7 @@ use std::{any::type_name, fmt}; use super::sealed::Sealed; use http::Uri; -use serde::Serialize; +use serde_core::Serialize; /// A type safe path. /// @@ -384,7 +384,6 @@ impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, #[cfg(test)] mod tests { - use super::*; use crate::{ extract::WithRejection, routing::{RouterExt, TypedPath}, @@ -394,7 +393,7 @@ mod tests { response::{IntoResponse, Response}, Router, }; - use serde::Deserialize; + use serde::{Deserialize, Serialize}; #[derive(TypedPath, Deserialize)] #[typed_path("/users/{id}")] diff --git a/axum-macros/tests/debug_handler/fail/json_not_deserialize.stderr b/axum-macros/tests/debug_handler/fail/json_not_deserialize.stderr index afda86b65d..a4b0cf9589 100644 --- a/axum-macros/tests/debug_handler/fail/json_not_deserialize.stderr +++ b/axum-macros/tests/debug_handler/fail/json_not_deserialize.stderr @@ -1,12 +1,12 @@ -error[E0277]: the trait bound `for<'de> Struct: serde::de::Deserialize<'de>` is not satisfied +error[E0277]: the trait bound `Struct: serde::Deserialize<'de>` is not satisfied --> tests/debug_handler/fail/json_not_deserialize.rs:7:24 | 7 | async fn handler(_foo: Json) {} - | ^^^^^^^^^^^^ the trait `for<'de> serde::de::Deserialize<'de>` is not implemented for `Struct`, which is required by `Json: FromRequest<()>` + | ^^^^^^^^^^^^ the trait `for<'de> serde_core::de::Deserialize<'de>` is not implemented for `Struct`, which is required by `Json: FromRequest<()>` | = note: for local types consider adding `#[derive(serde::Deserialize)]` to your `Struct` type = note: for types from other crates check whether the crate offers a `serde` feature flag - = help: the following other types implement trait `serde::de::Deserialize<'de>`: + = help: the following other types implement trait `serde_core::de::Deserialize<'de>`: &'a [u8] &'a serde_json::raw::RawValue &'a std::path::Path @@ -16,7 +16,7 @@ error[E0277]: the trait bound `for<'de> Struct: serde::de::Deserialize<'de>` is (T0, T1) (T0, T1, T2) and $N others - = note: required for `Struct` to implement `serde::de::DeserializeOwned` + = note: required for `Struct` to implement `serde_core::de::DeserializeOwned` = note: required for `Json` to implement `FromRequest<()>` = help: see issue #48214 help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -24,15 +24,15 @@ help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 1 + #![feature(trivial_bounds)] | -error[E0277]: the trait bound `for<'de> Struct: serde::de::Deserialize<'de>` is not satisfied +error[E0277]: the trait bound `Struct: serde::Deserialize<'de>` is not satisfied --> tests/debug_handler/fail/json_not_deserialize.rs:7:24 | 7 | async fn handler(_foo: Json) {} - | ^^^^^^^^^^^^ the trait `for<'de> serde::de::Deserialize<'de>` is not implemented for `Struct`, which is required by `Json: FromRequest<()>` + | ^^^^^^^^^^^^ the trait `for<'de> serde_core::de::Deserialize<'de>` is not implemented for `Struct`, which is required by `Json: FromRequest<()>` | = note: for local types consider adding `#[derive(serde::Deserialize)]` to your `Struct` type = note: for types from other crates check whether the crate offers a `serde` feature flag - = help: the following other types implement trait `serde::de::Deserialize<'de>`: + = help: the following other types implement trait `serde_core::de::Deserialize<'de>`: &'a [u8] &'a serde_json::raw::RawValue &'a std::path::Path @@ -42,7 +42,7 @@ error[E0277]: the trait bound `for<'de> Struct: serde::de::Deserialize<'de>` is (T0, T1) (T0, T1, T2) and $N others - = note: required for `Struct` to implement `serde::de::DeserializeOwned` + = note: required for `Struct` to implement `serde_core::de::DeserializeOwned` = note: required for `Json` to implement `FromRequest<()>` note: required by a bound in `__axum_macros_check_handler_0_from_request_check` --> tests/debug_handler/fail/json_not_deserialize.rs:7:24 diff --git a/axum-macros/tests/typed_path/fail/not_deserialize.stderr b/axum-macros/tests/typed_path/fail/not_deserialize.stderr index ed2c9d7571..4534b19eb3 100644 --- a/axum-macros/tests/typed_path/fail/not_deserialize.stderr +++ b/axum-macros/tests/typed_path/fail/not_deserialize.stderr @@ -1,12 +1,12 @@ -error[E0277]: the trait bound `for<'de> MyPath: serde::de::Deserialize<'de>` is not satisfied +error[E0277]: the trait bound `MyPath: serde::Deserialize<'de>` is not satisfied --> tests/typed_path/fail/not_deserialize.rs:3:10 | 3 | #[derive(TypedPath)] - | ^^^^^^^^^ the trait `for<'de> serde::de::Deserialize<'de>` is not implemented for `MyPath`, which is required by `axum::extract::Path: FromRequestParts` + | ^^^^^^^^^ the trait `for<'de> serde_core::de::Deserialize<'de>` is not implemented for `MyPath`, which is required by `axum::extract::Path: FromRequestParts` | = note: for local types consider adding `#[derive(serde::Deserialize)]` to your `MyPath` type = note: for types from other crates check whether the crate offers a `serde` feature flag - = help: the following other types implement trait `serde::de::Deserialize<'de>`: + = help: the following other types implement trait `serde_core::de::Deserialize<'de>`: &'a [u8] &'a serde_json::raw::RawValue &'a std::path::Path @@ -16,16 +16,16 @@ error[E0277]: the trait bound `for<'de> MyPath: serde::de::Deserialize<'de>` is (T0, T1) (T0, T1, T2) and $N others - = note: required for `MyPath` to implement `serde::de::DeserializeOwned` + = note: required for `MyPath` to implement `serde_core::de::DeserializeOwned` = note: required for `axum::extract::Path` to implement `FromRequestParts` error[E0277]: the trait bound `MyPath: serde::de::DeserializeOwned` is not satisfied --> tests/typed_path/fail/not_deserialize.rs:3:10 | 3 | #[derive(TypedPath)] - | ^^^^^^^^^ the trait `for<'de> serde::de::Deserialize<'de>` is not implemented for `MyPath`, which is required by `axum::extract::Path: FromRequestParts` + | ^^^^^^^^^ the trait `for<'de> serde_core::de::Deserialize<'de>` is not implemented for `MyPath`, which is required by `axum::extract::Path: FromRequestParts` | - = help: the following other types implement trait `serde::de::Deserialize<'de>`: + = help: the following other types implement trait `serde_core::de::Deserialize<'de>`: &'a [u8] &'a serde_json::raw::RawValue &'a std::path::Path @@ -35,16 +35,16 @@ error[E0277]: the trait bound `MyPath: serde::de::DeserializeOwned` is not satis (T0, T1) (T0, T1, T2) and $N others - = note: required for `MyPath` to implement `serde::de::DeserializeOwned` + = note: required for `MyPath` to implement `serde_core::de::DeserializeOwned` = note: required for `axum::extract::Path` to implement `FromRequestParts` error[E0277]: the trait bound `MyPath: serde::de::DeserializeOwned` is not satisfied --> tests/typed_path/fail/not_deserialize.rs:3:10 | 3 | #[derive(TypedPath)] - | ^^^^^^^^^ the trait `for<'de> serde::de::Deserialize<'de>` is not implemented for `MyPath`, which is required by `axum::extract::Path: FromRequestParts` + | ^^^^^^^^^ the trait `for<'de> serde_core::de::Deserialize<'de>` is not implemented for `MyPath`, which is required by `axum::extract::Path: FromRequestParts` | - = help: the following other types implement trait `serde::de::Deserialize<'de>`: + = help: the following other types implement trait `serde_core::de::Deserialize<'de>`: &'a [u8] &'a serde_json::raw::RawValue &'a std::path::Path @@ -54,6 +54,6 @@ error[E0277]: the trait bound `MyPath: serde::de::DeserializeOwned` is not satis (T0, T1) (T0, T1, T2) and $N others - = note: required for `MyPath` to implement `serde::de::DeserializeOwned` + = note: required for `MyPath` to implement `serde_core::de::DeserializeOwned` = note: required for `axum::extract::Path` to implement `FromRequestParts` = note: this error originates in the derive macro `TypedPath` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/axum/Cargo.toml b/axum/Cargo.toml index 797eea0819..393074f0f7 100644 --- a/axum/Cargo.toml +++ b/axum/Cargo.toml @@ -33,7 +33,7 @@ allowed = [ "bytes", "http", "http_body", - "serde", + "serde_core", "tokio", # for the `__private` feature "reqwest", @@ -78,6 +78,7 @@ __private_docs = [ "axum-core/__private_docs", # Enables upstream things linked to in docs "tower/full", + "dep:serde", "dep:tower-http", ] @@ -100,7 +101,7 @@ memchr = "2.4.1" mime = "0.3.16" percent-encoding = "2.1" pin-project-lite = "0.2.7" -serde = "1.0" +serde_core = "1.0.221" sync_wrapper = "1.0.0" tower = { version = "0.5.2", default-features = false, features = ["util"] } tower-layer = "0.3.2" @@ -122,6 +123,9 @@ tokio = { package = "tokio", version = "1.44", features = ["time"], optional = t tokio-tungstenite = { version = "0.27.0", optional = true } tracing = { version = "0.1", default-features = false, optional = true } +# doc dependencies +serde = { version = "1.0.211", optional = true } + [dependencies.tower-http] version = "0.6.0" optional = true @@ -165,7 +169,7 @@ hyper = { version = "1.1.0", features = ["client"] } quickcheck = "1.0" quickcheck_macros = "1.0" reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] } -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.221", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } time = { version = "0.3", features = ["serde-human-readable"] } tokio = { package = "tokio", version = "1.44.2", features = ["macros", "rt", "rt-multi-thread", "net", "test-util"] } diff --git a/axum/src/extract/path/de.rs b/axum/src/extract/path/de.rs index aae2ac7b75..929f0c1f53 100644 --- a/axum/src/extract/path/de.rs +++ b/axum/src/extract/path/de.rs @@ -1,6 +1,6 @@ use super::{ErrorKind, PathDeserializationError}; use crate::util::PercentDecodedStr; -use serde::{ +use serde_core::{ de::{self, DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor}, forward_to_deserialize_any, Deserializer, }; diff --git a/axum/src/extract/path/mod.rs b/axum/src/extract/path/mod.rs index c2c01a039b..44b2a32311 100644 --- a/axum/src/extract/path/mod.rs +++ b/axum/src/extract/path/mod.rs @@ -14,7 +14,7 @@ use axum_core::{ RequestPartsExt as _, }; use http::{request::Parts, StatusCode}; -use serde::de::DeserializeOwned; +use serde_core::de::DeserializeOwned; use std::{fmt, sync::Arc}; /// Extractor that will get captures from the URL and parse them using @@ -254,7 +254,7 @@ impl WrongNumberOfParameters { } } -impl serde::de::Error for PathDeserializationError { +impl serde_core::de::Error for PathDeserializationError { #[inline] fn custom(msg: T) -> Self where @@ -710,7 +710,7 @@ mod tests { async fn captures_match_empty_inner_segments() { let app = Router::new().route( "/{key}/method", - get(|Path(param): Path| async move { param.to_string() }), + get(|Path(param): Path| async move { param.clone() }), ); let client = TestClient::new(app); @@ -726,7 +726,7 @@ mod tests { async fn captures_match_empty_inner_segments_near_end() { let app = Router::new().route( "/method/{key}/", - get(|Path(param): Path| async move { param.to_string() }), + get(|Path(param): Path| async move { param.clone() }), ); let client = TestClient::new(app); @@ -745,7 +745,7 @@ mod tests { async fn captures_match_empty_trailing_segment() { let app = Router::new().route( "/method/{key}", - get(|Path(param): Path| async move { param.to_string() }), + get(|Path(param): Path| async move { param.clone() }), ); let client = TestClient::new(app); diff --git a/axum/src/extract/query.rs b/axum/src/extract/query.rs index b06c7f3e53..870acb76c3 100644 --- a/axum/src/extract/query.rs +++ b/axum/src/extract/query.rs @@ -1,6 +1,6 @@ use super::{rejection::*, FromRequestParts}; use http::{request::Parts, Uri}; -use serde::de::DeserializeOwned; +use serde_core::de::DeserializeOwned; /// Extractor that deserializes query strings into some type. /// diff --git a/axum/src/form.rs b/axum/src/form.rs index eb499def73..a28dddd51d 100644 --- a/axum/src/form.rs +++ b/axum/src/form.rs @@ -4,8 +4,7 @@ use axum_core::response::{IntoResponse, Response}; use axum_core::RequestExt; use http::header::CONTENT_TYPE; use http::StatusCode; -use serde::de::DeserializeOwned; -use serde::Serialize; +use serde_core::{de::DeserializeOwned, Serialize}; /// URL encoded extractor and response. /// diff --git a/axum/src/json.rs b/axum/src/json.rs index 36cf230e1a..5eec9c2ec9 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -7,7 +7,7 @@ use http::{ header::{self, HeaderMap, HeaderValue}, StatusCode, }; -use serde::{de::DeserializeOwned, Serialize}; +use serde_core::{de::DeserializeOwned, Serialize}; /// JSON Extractor / Response. /// diff --git a/axum/src/response/sse.rs b/axum/src/response/sse.rs index 974a4939dd..cb2892191e 100644 --- a/axum/src/response/sse.rs +++ b/axum/src/response/sse.rs @@ -255,7 +255,7 @@ impl Event { #[cfg(feature = "json")] pub fn json_data(self, data: T) -> Result where - T: serde::Serialize, + T: serde_core::Serialize, { struct JsonWriter<'a>(&'a mut EventDataWriter); impl std::io::Write for JsonWriter<'_> { diff --git a/axum/src/test_helpers/test_client.rs b/axum/src/test_helpers/test_client.rs index 8f239e57c5..135933a3fa 100644 --- a/axum/src/test_helpers/test_client.rs +++ b/axum/src/test_helpers/test_client.rs @@ -102,7 +102,7 @@ impl RequestBuilder { pub fn json(mut self, json: &T) -> Self where - T: serde::Serialize, + T: serde_core::Serialize, { self.builder = self.builder.json(json); self @@ -165,7 +165,7 @@ impl TestResponse { #[allow(dead_code)] pub async fn json(self) -> T where - T: serde::de::DeserializeOwned, + T: serde_core::de::DeserializeOwned, { self.response.json().await.unwrap() }