Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OwnedLazyValue does not work in enum cases #84

Open
bluealert opened this issue May 23, 2024 · 3 comments
Open

OwnedLazyValue does not work in enum cases #84

bluealert opened this issue May 23, 2024 · 3 comments

Comments

@bluealert
Copy link

bluealert commented May 23, 2024

Describe the bug
When I have to deserialize several different json objects, I want to use enum to unify the deserialization. And I also want to use OwnedLazyValue, but I found that the OwnedLazyValue does not work in enum cases.

To Reproduce

use serde::Deserialize;
use serde_json::Value;
use sonic_rs::OwnedLazyValue;

#[derive(Debug, Deserialize)]
struct A {
    #[serde(deserialize_with = "deserialize_owned_lazy_value")]
    field1: OwnedLazyValue,
    field2: String,
}

#[derive(Debug, Deserialize)]
struct B {
    field_a: String,
    field_b: String,
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum JsonObject {
    A(A),
    B(B),
}

fn deserialize_owned_lazy_value<'de, D>(
    deserializer: D,
) -> Result<OwnedLazyValue, D::Error>
where
    D: serde::Deserializer<'de>,
{
    let value = Value::deserialize(deserializer)?;
    sonic_rs::from_str(&value.to_string()).map_err(serde::de::Error::custom)
}

fn process_json(json_str: &str) {
    let json_obj: Result<JsonObject, _> = serde_json::from_str(json_str);

    match json_obj {
        Ok(JsonObject::A(a)) => {
            println!("A: {:?}, {:?}", a.field1, a.field2);
        }
        Ok(JsonObject::B(b)) => {
            println!("B: {:?}, {:?}", b.field_a, b.field_b);
        }
        Err(e) => eprintln!("Failed to parse JSON: {}", e),
    }
}

fn main() {
    let json_str1 = r#"{ "field1": "value1", "field2": "value2" }"#;
    let json_str2 = r#"{ "field_a": "valueA", "field_b": "valueB" }"#;

    process_json(json_str1);
    process_json(json_str2);
}

I must use deserialize_owned_lazy_value to deserialize field1.

Expected behavior

I want the OwnedLazyValue works as in not enum cases. I don't need to write my own deserialization function.

sonic-rs version:
0.3

Environment:
Ubuntu 22.04, Rust 1.77

@liuq19
Copy link
Collaborator

liuq19 commented May 23, 2024

Thanks, i will investigate it

@liuq19 liuq19 mentioned this issue May 23, 2024
9 tasks
@CPunisher
Copy link
Contributor

CPunisher commented Aug 30, 2024

deserializer.deserialize_newtype_struct(super::TOKEN, visit)

I'm not sure. According to this implementation, we can know that sonic_rs::Value, sonic_rs::LazyValue and sonic_rs::OwnedLazyValue are different from serde::Value. They can only deserialize from structure strings like { ... } compared to https://github.com/serde-rs/json/blob/27a4ca9d7a62394fe8f0103f3d91de59f055a4c4/src/value/de.rs#L135

The following code works:

fn main() {
    let json_str1 = r#"{ "field1": { "value": "value1" }, "field2": "value2" }"#;
    let json_str2 = r#"{ "field_a": "valueA", "field_b": "valueB" }"#;

    process_json(json_str1);
    process_json(json_str2);
}

@liuq19
Copy link
Collaborator

liuq19 commented Aug 30, 2024

this is an expected behavior because we hacked the visitor when using Value or LazyValue, likes serve-json::RawValue.

@liuq19 liuq19 closed this as completed Aug 30, 2024
@liuq19 liuq19 reopened this Sep 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants