Skip to content

Commit

Permalink
[ISSUE #704]🚀Add SerdeJsonUtils struct tool 🚀 (#705)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxsm authored Jun 28, 2024
1 parent 5f6a7f5 commit 24c6f65
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rocketmq-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ time = "0.3.36"
dashmap = "6.0.1"
hostname = "0.4"
regex = "1.10.5"
thiserror = { workspace = true }
[dev-dependencies]
mockall = "0.12.1"
23 changes: 23 additions & 0 deletions rocketmq-common/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use thiserror::Error;

#[derive(Debug, Error)]
pub enum SerdeJsonError {
#[error("Serialization error: {0}")]
JsonError(#[from] serde_json::Error),
}
1 change: 1 addition & 0 deletions rocketmq-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub use crate::utils::time_utils as TimeUtils;
pub use crate::utils::util_all as UtilAll;

pub mod common;
pub mod error;
pub mod log;
mod thread_pool;
pub mod utils;
Expand Down
201 changes: 201 additions & 0 deletions rocketmq-common/src/utils/serde_json_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::error::SerdeJsonError;

pub struct SerdeJsonUtils;

impl SerdeJsonUtils {
pub fn from_json<T>(json: &str) -> Result<T, SerdeJsonError>
where
T: serde::de::DeserializeOwned,
{
serde_json::from_str(json).map_err(SerdeJsonError::JsonError)
}

pub fn from_json_slice<T>(json: &[u8]) -> Result<T, SerdeJsonError>
where
T: serde::de::DeserializeOwned,
{
serde_json::from_slice(json).map_err(SerdeJsonError::JsonError)
}

pub fn to_json<T>(value: &T) -> Result<String, SerdeJsonError>
where
T: serde::Serialize,
{
serde_json::to_string(value).map_err(SerdeJsonError::JsonError)
}

pub fn to_json_pretty<T>(value: &T) -> Result<String, SerdeJsonError>
where
T: serde::Serialize,
{
serde_json::to_string_pretty(value).map_err(SerdeJsonError::JsonError)
}

pub fn to_json_vec<T>(value: &T) -> Result<Vec<u8>, SerdeJsonError>
where
T: serde::Serialize,
{
serde_json::to_vec(value).map_err(SerdeJsonError::JsonError)
}

pub fn to_json_vec_pretty<T>(value: &T) -> Result<Vec<u8>, SerdeJsonError>
where
T: serde::Serialize,
{
serde_json::to_vec_pretty(value).map_err(SerdeJsonError::JsonError)
}
}

#[cfg(test)]
mod tests {
use serde_json::json;
use serde_json::Value;

use super::*;

#[test]
fn from_json_returns_expected_result() {
let json = r#"{"key": "value"}"#;
let result: Result<Value, _> = SerdeJsonUtils::from_json(json);
assert!(result.is_ok());
}

#[test]
fn from_json_returns_error_for_invalid_json() {
let json = "invalid";
let result: Result<Value, _> = SerdeJsonUtils::from_json(json);
assert!(result.is_err());
}

#[test]
fn from_json_slice_returns_expected_result() {
let json = r#"{"key": "value"}"#.as_bytes();
let result: Result<Value, _> = SerdeJsonUtils::from_json_slice(json);
assert!(result.is_ok());
}

#[test]
fn from_json_slice_returns_error_for_invalid_json() {
let json = "invalid".as_bytes();
let result: Result<Value, _> = SerdeJsonUtils::from_json_slice(json);
assert!(result.is_err());
}

#[test]
fn to_json_returns_expected_result() {
let value = json!({"key": "value"});
let result = SerdeJsonUtils::to_json(&value);
assert!(result.is_ok());
}

#[test]
fn to_json_pretty_returns_expected_result() {
let value = json!({"key": "value"});
let result = SerdeJsonUtils::to_json_pretty(&value);
assert!(result.is_ok());
}

#[test]
fn to_json_vec_returns_expected_result() {
let value = json!({"key": "value"});
let result = SerdeJsonUtils::to_json_vec(&value);
assert!(result.is_ok());
}

#[test]
fn to_json_vec_pretty_returns_expected_result() {
let value = json!({"key": "value"});
let result = SerdeJsonUtils::to_json_vec_pretty(&value);
assert!(result.is_ok());
}

use std::fmt::Debug;

use serde::Deserialize;
use serde::Serialize;
use serde_json::Error;

#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct TestStruct {
name: String,
age: u8,
}

#[test]
fn test_from_json_success() {
let json_str = r#"{"name":"Alice","age":30}"#;
let expected = TestStruct {
name: "Alice".to_string(),
age: 30,
};
let result: TestStruct = SerdeJsonUtils::from_json(json_str).unwrap();
assert_eq!(result, expected);
}

#[test]
fn test_from_json_error() {
let json_str = r#"{"name":"Alice","age":"thirty"}"#;
let result: Result<TestStruct, SerdeJsonError> = SerdeJsonUtils::from_json(json_str);
assert!(result.is_err());
}

#[test]
fn test_from_json_slice_success() {
let json_slice = r#"{"name":"Bob","age":25}"#.as_bytes();
let expected = TestStruct {
name: "Bob".to_string(),
age: 25,
};
let result: TestStruct = SerdeJsonUtils::from_json_slice(json_slice).unwrap();
assert_eq!(result, expected);
}

#[test]
fn test_from_json_slice_error() {
let json_slice = r#"{"name":"Bob","age":"twenty-five"}"#.as_bytes();
let result: Result<TestStruct, SerdeJsonError> =
SerdeJsonUtils::from_json_slice(json_slice);
assert!(result.is_err());
}

#[test]
fn test_to_json_success() {
let value = TestStruct {
name: "Charlie".to_string(),
age: 40,
};
let expected = r#"{"name":"Charlie","age":40}"#;
let result: String = SerdeJsonUtils::to_json(&value).unwrap();
assert_eq!(result, expected);
}

#[test]
fn test_to_json_error() {
// This test is a bit tricky since `to_json` should not normally fail
// unless there's a bug in `serde_json`. We can't really force an error
// in a meaningful way, so we'll just ensure that the method returns a
// `Result` and does not panic.
let value = TestStruct {
name: "Charlie".to_string(),
age: 40,
};
let result: Result<String, SerdeJsonError> = SerdeJsonUtils::to_json(&value);
assert!(result.is_ok());
}
}

0 comments on commit 24c6f65

Please sign in to comment.