iddm / serde-aux

An auxiliary serde library providing helpful functions for serialisation and deserialisation for containers, struct fields and others.
MIT License
152 stars 26 forks source link

deserialize_default_from_empty_object with null value #12

Closed georgemp closed 3 years ago

georgemp commented 3 years ago

With the following code, I get an error when the incoming json has a null value for a field.

extern crate serde;
extern crate serde_aux;
extern crate serde_json;

use serde::{Deserialize, Serialize};
use serde_aux::prelude::*;

#[derive(Serialize, Deserialize, Debug, Default)]
struct MyStruct {
    #[serde(deserialize_with = "deserialize_default_from_empty_object")]
    name: String,
}

fn main() {
    let s = r#" {"name": "George" }"#;
    let a: MyStruct = serde_json::from_str(s).unwrap();
    assert_eq!(a.name, "George");

    let s = r#" { "name": {} } "#;
    let a: MyStruct = serde_json::from_str(s).unwrap();
    assert_eq!(a.name, "");

    let s = r#" { "name": null} "#;
    let a: MyStruct = serde_json::from_str(s).unwrap();
    assert_eq!(a.name, "");
}

The error is

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("data did not match any variant of untagged enum EmptyOrNot", line: 1, column: 16)', src/main.rs:38:47
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Strangely, enough the following code does not error, the name field in MyStruct is now wrapped in an Option (as in the documentation example)

extern crate serde;
extern crate serde_aux;
extern crate serde_json;

use serde::{Deserialize, Serialize};
use serde_aux::prelude::*;

#[derive(Serialize, Deserialize, Debug, Default)]
struct MyStruct {
    #[serde(deserialize_with = "deserialize_default_from_empty_object")]
    name: Option<String>,
}

fn main() {
    let s = r#" {"name": "George" }"#;
    let a: MyStruct = serde_json::from_str(s).unwrap();
    assert_eq!(a.name, Some("George".to_owned()));

    let s = r#" { "name": {} } "#;
    let a: MyStruct = serde_json::from_str(s).unwrap();
    assert_eq!(a.name, None);

    let s = r#" { "name": null} "#;
    let a: MyStruct = serde_json::from_str(s).unwrap();
    assert_eq!(a.name, None);
}
iddm commented 3 years ago

Thanks for your contribution. What rust version, all the crates versions you are using?

georgemp commented 3 years ago

Rust v1.46.0 serde v1.0.118 serde_json v1.0.61 serde-aux v2.1.0

Full Cargo.lock

# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "chrono"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
 "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
 "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "itoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "libc"
version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "num-integer"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "num-traits"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "ryu"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "serde"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "serde_derive 1.0.118 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde-aux"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde 1.0.118 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde_json 1.0.61 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_default_empty"
version = "0.1.0"
dependencies = [
 "serde 1.0.118 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde-aux 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde_json 1.0.61 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_derive"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_json"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde 1.0.118 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "syn"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[metadata]
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
"checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
"checksum serde 1.0.118 (registry+https://github.com/rust-lang/crates.io-index)" = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
"checksum serde-aux 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a16764e861bd10990815d72767548131b2084079170bedec7cbf5a8ade2daeb"
"checksum serde_derive 1.0.118 (registry+https://github.com/rust-lang/crates.io-index)" = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
"checksum serde_json 1.0.61 (registry+https://github.com/rust-lang/crates.io-index)" = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
"checksum syn 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"
iddm commented 3 years ago

I see what's the problem here, the null value either has always been handled differently or it has changed. I'll try doing my best at fixing this as soon as possible.

iddm commented 3 years ago

I have just published 2.1.1, can you please verify that it no longer appears for you using this new version?

georgemp commented 3 years ago

Thanks for that extremely quick fix. I don't see the issue with the new version.

iddm commented 3 years ago

Should you find anything else, please do not hesitate to create an issue! Have a nice day!