Skip to content

Commit d0ea428

Browse files
committed
Add encode_empty_tables_as_array serialize option.
This will change the behaviour of encoding empty Lua tables into array instead of map.
1 parent 3e87d3e commit d0ea428

4 files changed

Lines changed: 82 additions & 1 deletion

File tree

src/serde/de.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ pub struct Options {
4949
///
5050
/// Default: **false**
5151
pub sort_keys: bool,
52+
53+
/// If true, empty Lua tables will be encoded as array, instead of map.
54+
///
55+
/// Default: **false**
56+
pub encode_empty_tables_as_array: bool,
5257
}
5358

5459
impl Default for Options {
@@ -64,6 +69,7 @@ impl Options {
6469
deny_unsupported_types: true,
6570
deny_recursive_tables: true,
6671
sort_keys: false,
72+
encode_empty_tables_as_array: false,
6773
}
6874
}
6975

@@ -93,6 +99,15 @@ impl Options {
9399
self.sort_keys = enabled;
94100
self
95101
}
102+
103+
/// Sets [`encode_empty_tables_as_array`] option.
104+
///
105+
/// [`encode_empty_tables_as_array`]: #structfield.encode_empty_tables_as_array
106+
#[must_use]
107+
pub const fn encode_empty_tables_as_array(mut self, enabled: bool) -> Self {
108+
self.encode_empty_tables_as_array = enabled;
109+
self
110+
}
96111
}
97112

98113
impl Deserializer {
@@ -141,6 +156,9 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
141156
Err(_) => visitor.visit_bytes(&s.as_bytes()),
142157
},
143158
Value::Table(ref t) if t.raw_len() > 0 || t.is_array() => self.deserialize_seq(visitor),
159+
Value::Table(ref t) if self.options.encode_empty_tables_as_array && t.is_empty() => {
160+
self.deserialize_seq(visitor)
161+
}
144162
Value::Table(_) => self.deserialize_map(visitor),
145163
Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_none(),
146164
Value::UserData(ud) if ud.is_serializable() => {

src/table.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,10 @@ impl Serialize for SerializableTable<'_> {
10201020

10211021
// Array
10221022
let len = self.table.raw_len();
1023-
if len > 0 || self.table.is_array() {
1023+
if len > 0
1024+
|| self.table.is_array()
1025+
|| (self.options.encode_empty_tables_as_array && self.table.is_empty())
1026+
{
10241027
let mut seq = serializer.serialize_seq(Some(len))?;
10251028
let mut serialize_err = None;
10261029
let res = self.table.for_each_value::<Value>(|value| {

src/value.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,15 @@ impl<'a> SerializableValue<'a> {
700700
self.options.sort_keys = enabled;
701701
self
702702
}
703+
704+
/// If true, empty Lua tables will be encoded as array, instead of map.
705+
///
706+
/// Default: **false**
707+
#[must_use]
708+
pub const fn encode_empty_tables_as_array(mut self, enabled: bool) -> Self {
709+
self.options.encode_empty_tables_as_array = enabled;
710+
self
711+
}
703712
}
704713

705714
#[cfg(feature = "serialize")]

tests/serde.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,26 @@ fn test_serialize_same_table_twice() -> LuaResult<()> {
249249
Ok(())
250250
}
251251

252+
#[test]
253+
fn test_serialize_empty_table() -> LuaResult<()> {
254+
let lua = Lua::new();
255+
256+
let table = Value::Table(lua.create_table()?);
257+
let json = serde_json::to_string(&table.to_serializable()).unwrap();
258+
assert_eq!(json, "{}");
259+
260+
// Set the option to encode empty tables as array
261+
let json = serde_json::to_string(&table.to_serializable().encode_empty_tables_as_array(true)).unwrap();
262+
assert_eq!(json, "[]");
263+
264+
// Check hashmap table with this option
265+
table.as_table().unwrap().set("hello", "world")?;
266+
let json = serde_json::to_string(&table.to_serializable().encode_empty_tables_as_array(true)).unwrap();
267+
assert_eq!(json, r#"{"hello":"world"}"#);
268+
269+
Ok(())
270+
}
271+
252272
#[test]
253273
fn test_to_value_struct() -> LuaResult<()> {
254274
let lua = Lua::new();
@@ -667,6 +687,37 @@ fn test_from_value_userdata() -> Result<(), Box<dyn StdError>> {
667687
Ok(())
668688
}
669689

690+
#[test]
691+
fn test_from_value_empty_table() -> Result<(), Box<dyn StdError>> {
692+
let lua = Lua::new();
693+
694+
// By default we encode empty tables as objects
695+
let t = lua.create_table()?;
696+
let got = lua.from_value::<serde_json::Value>(Value::Table(t.clone()))?;
697+
assert_eq!(got, serde_json::json!({}));
698+
699+
// Set the option to encode empty tables as array
700+
let got = lua
701+
.from_value_with::<serde_json::Value>(
702+
Value::Table(t.clone()),
703+
DeserializeOptions::new().encode_empty_tables_as_array(true),
704+
)
705+
.unwrap();
706+
assert_eq!(got, serde_json::json!([]));
707+
708+
// Check hashmap table with this option
709+
t.raw_set("hello", "world")?;
710+
let got = lua
711+
.from_value_with::<serde_json::Value>(
712+
Value::Table(t),
713+
DeserializeOptions::new().encode_empty_tables_as_array(true),
714+
)
715+
.unwrap();
716+
assert_eq!(got, serde_json::json!({"hello": "world"}));
717+
718+
Ok(())
719+
}
720+
670721
#[test]
671722
fn test_from_value_sorted() -> Result<(), Box<dyn StdError>> {
672723
let lua = Lua::new();

0 commit comments

Comments
 (0)