Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ license = "Apache-2.0"
name = "sonic-rs"
readme = "README.md"
repository = "https://github.com/cloudwego/sonic-rs"
version = "0.5.5"
version = "0.5.6"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create a git tag?


# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
18 changes: 18 additions & 0 deletions scripts/fmt_fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

cd "${REPO_ROOT}"

echo "Updating Rust toolchain..."
rustup update

if [[ "${1:-}" == "--check" ]]; then
cargo fmt --all -- --check
else
cargo fmt --all
fi

5 changes: 5 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ pub(crate) struct DeserializeCfg {
pub use_rawnumber: bool,
pub utf8_lossy: bool,
}

#[derive(Debug, Clone, Copy, Default)]
pub(crate) struct SerializeCfg {
pub sort_map_keys: bool,
}
2 changes: 1 addition & 1 deletion src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{serde::tri, util::string::format_string, writer::WriteExt};

/// This trait abstracts away serializing the JSON control characters, which allows the user to
/// optionally pretty print the JSON output.
pub trait Formatter {
pub trait Formatter: Clone {
/// Writes a `null` value to the specified writer.
#[inline]
fn write_null<W>(&mut self, writer: &mut W) -> io::Result<()>
Expand Down
80 changes: 79 additions & 1 deletion src/serde/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod test {

use bytes::Bytes;
use faststr::FastStr;
use serde::{de::IgnoredAny, Deserialize, Serialize};
use serde::{de::IgnoredAny, ser::SerializeMap, Deserialize, Serialize};

use super::*;
use crate::{Result, Value};
Expand All @@ -50,6 +50,84 @@ mod test {
};
}

struct UnorderedMap<'a> {
entries: &'a [(&'a str, u8)],
}

impl Serialize for UnorderedMap<'_> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(self.entries.len()))?;
for (key, value) in self.entries {
map.serialize_entry(key, value)?;
}
map.end()
}
}

#[test]
fn test_serializer_sort_map_keys_toggle() {
let entries = [("b", 1u8), ("a", 2u8), ("c", 3u8)];
let unordered = UnorderedMap { entries: &entries };

let mut ser = Serializer::new(Vec::new());
unordered.serialize(&mut ser).unwrap();
let output = String::from_utf8(ser.into_inner()).unwrap();
let expected_default = r#"{"b":1,"a":2,"c":3}"#;
assert_eq!(output, expected_default);

let mut ser = Serializer::new(Vec::new()).sort_map_keys();
unordered.serialize(&mut ser).unwrap();
let output = String::from_utf8(ser.into_inner()).unwrap();
assert_eq!(output, r#"{"a":2,"b":1,"c":3}"#);
}

#[test]
fn test_value_to_string_sort_behavior() {
let value: Value = crate::json!({"b": 1, "a": 2, "c": 3});

let json = to_string(&value).unwrap();
let expected_sorted = r#"{"a":2,"b":1,"c":3}"#;

if cfg!(feature = "sort_keys") {
assert_eq!(json, expected_sorted);
} else {
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed, serde_json::json!({"b": 1, "a": 2, "c": 3}));
}

let mut ser = Serializer::new(Vec::new()).sort_map_keys();
value.serialize(&mut ser).unwrap();
let sorted_json = String::from_utf8(ser.into_inner()).unwrap();
assert_eq!(sorted_json, expected_sorted);
}

#[test]
fn test_value_serializer_sort_map_keys() {
let value: Value = crate::json!({"delta": 4, "beta": 2, "alpha": 1});

let mut ser = Serializer::new(Vec::new());
value.serialize(&mut ser).unwrap();
let default_json = String::from_utf8(ser.into_inner()).unwrap();

if cfg!(feature = "sort_keys") {
assert_eq!(default_json, r#"{"alpha":1,"beta":2,"delta":4}"#);
} else {
let parsed: serde_json::Value = serde_json::from_str(&default_json).unwrap();
assert_eq!(
parsed,
serde_json::json!({"delta": 4, "beta": 2, "alpha": 1})
);
}

let mut ser = Serializer::new(Vec::new()).sort_map_keys();
value.serialize(&mut ser).unwrap();
let sorted = String::from_utf8(ser.into_inner()).unwrap();
assert_eq!(sorted, r#"{"alpha":1,"beta":2,"delta":4}"#);
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
struct Foo {
name: FastStr,
Expand Down
Loading
Loading