mirror of
https://github.com/tokio-rs/axum.git
synced 2024-12-28 23:38:20 +01:00
Json: add from_bytes method, use that in 'impl FromRequest' (#2244)
Signed-off-by: wayne warren <wayne.warren.s@gmail.com> Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
This commit is contained in:
parent
c100650464
commit
0c7ff7c76b
2 changed files with 39 additions and 25 deletions
|
@ -66,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- **added:** Implement `IntoResponse` for `(R,) where R: IntoResponse` ([#2143])
|
- **added:** Implement `IntoResponse` for `(R,) where R: IntoResponse` ([#2143])
|
||||||
- **changed:** For SSE, add space between field and value for compatibility ([#2149])
|
- **changed:** For SSE, add space between field and value for compatibility ([#2149])
|
||||||
- **added:** Add `NestedPath` extractor ([#1924])
|
- **added:** Add `NestedPath` extractor ([#1924])
|
||||||
|
- **added:** Add `axum::Json::from_bytes` ([#2244])
|
||||||
|
|
||||||
[#1664]: https://github.com/tokio-rs/axum/pull/1664
|
[#1664]: https://github.com/tokio-rs/axum/pull/1664
|
||||||
[#1751]: https://github.com/tokio-rs/axum/pull/1751
|
[#1751]: https://github.com/tokio-rs/axum/pull/1751
|
||||||
|
@ -86,6 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
[#2140]: https://github.com/tokio-rs/axum/pull/2140
|
[#2140]: https://github.com/tokio-rs/axum/pull/2140
|
||||||
[#2143]: https://github.com/tokio-rs/axum/pull/2143
|
[#2143]: https://github.com/tokio-rs/axum/pull/2143
|
||||||
[#2149]: https://github.com/tokio-rs/axum/pull/2149
|
[#2149]: https://github.com/tokio-rs/axum/pull/2149
|
||||||
|
[#2244]: https://github.com/tokio-rs/axum/pull/2244
|
||||||
|
|
||||||
# 0.6.17 (25. April, 2023)
|
# 0.6.17 (25. April, 2023)
|
||||||
|
|
||||||
|
|
|
@ -103,31 +103,7 @@ where
|
||||||
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
||||||
if json_content_type(req.headers()) {
|
if json_content_type(req.headers()) {
|
||||||
let bytes = Bytes::from_request(req, state).await?;
|
let bytes = Bytes::from_request(req, state).await?;
|
||||||
let deserializer = &mut serde_json::Deserializer::from_slice(&bytes);
|
Self::from_bytes(&bytes)
|
||||||
|
|
||||||
let value = match serde_path_to_error::deserialize(deserializer) {
|
|
||||||
Ok(value) => value,
|
|
||||||
Err(err) => {
|
|
||||||
let rejection = match err.inner().classify() {
|
|
||||||
serde_json::error::Category::Data => JsonDataError::from_err(err).into(),
|
|
||||||
serde_json::error::Category::Syntax | serde_json::error::Category::Eof => {
|
|
||||||
JsonSyntaxError::from_err(err).into()
|
|
||||||
}
|
|
||||||
serde_json::error::Category::Io => {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
// we don't use `serde_json::from_reader` and instead always buffer
|
|
||||||
// bodies first, so we shouldn't encounter any IO errors
|
|
||||||
unreachable!()
|
|
||||||
} else {
|
|
||||||
JsonSyntaxError::from_err(err).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return Err(rejection);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Json(value))
|
|
||||||
} else {
|
} else {
|
||||||
Err(MissingJsonContentType.into())
|
Err(MissingJsonContentType.into())
|
||||||
}
|
}
|
||||||
|
@ -167,6 +143,42 @@ impl<T> From<T> for Json<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Json<T>
|
||||||
|
where
|
||||||
|
T: DeserializeOwned,
|
||||||
|
{
|
||||||
|
/// Construct a `Json<T>` from a byte slice. Most users should prefer to use the `FromRequest` impl
|
||||||
|
/// but special cases may require first extracting a `Request` into `Bytes` then optionally
|
||||||
|
/// constructing a `Json<T>`.
|
||||||
|
pub fn from_bytes(bytes: &[u8]) -> Result<Self, JsonRejection> {
|
||||||
|
let deserializer = &mut serde_json::Deserializer::from_slice(bytes);
|
||||||
|
|
||||||
|
let value = match serde_path_to_error::deserialize(deserializer) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(err) => {
|
||||||
|
let rejection = match err.inner().classify() {
|
||||||
|
serde_json::error::Category::Data => JsonDataError::from_err(err).into(),
|
||||||
|
serde_json::error::Category::Syntax | serde_json::error::Category::Eof => {
|
||||||
|
JsonSyntaxError::from_err(err).into()
|
||||||
|
}
|
||||||
|
serde_json::error::Category::Io => {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
// we don't use `serde_json::from_reader` and instead always buffer
|
||||||
|
// bodies first, so we shouldn't encounter any IO errors
|
||||||
|
unreachable!()
|
||||||
|
} else {
|
||||||
|
JsonSyntaxError::from_err(err).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Err(rejection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Json(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> IntoResponse for Json<T>
|
impl<T> IntoResponse for Json<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
|
|
Loading…
Reference in a new issue