Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Unable to deserialize number as string for HashMap if flattened or inside untagged enum #414

Open
vallentin opened this issue Mar 7, 2024 · 0 comments

Comments

@vallentin
Copy link

vallentin commented Mar 7, 2024

Given the following YAML:

env:
  foo: 123
  • It successfully deserializes, when env: HashMap<String, String> is inside a struct
  • It fails to deserialize if inside an untagged enum
  • It fails to deserialize if the struct is flattened inside another struct
  • It successfully deserializes if struct is not flattened inside another struct

I understand why. It just feels very inconsistent. It seems that 123 gets deserialized into a number, before the context of interpreting it as a string is known. So that context is lost, and it then fails to deserialize.

Minimal Example

Rust Playground

#![allow(dead_code)]

use serde::Deserialize;
use std::collections::HashMap;

#[derive(Deserialize, Debug)]
struct Data1 {
    env: HashMap<String, String>,
}

#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum Data2 {
    Data { env: HashMap<String, String> },
}

#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum Data3 {
    Data(Data1),
}

#[derive(Deserialize, Debug)]
struct Data4 {
    #[serde(flatten)]
    dat: Data1,
}

fn main() {
    let yaml = r#"
    env:
      foo: bar
    "#;

    println!();
    let dat = serde_yaml::from_str::<Data1>(yaml); // Ok
    println!("{:?}", dat);
    let dat = serde_yaml::from_str::<Data2>(yaml); // Ok
    println!("{:?}", dat);
    let dat = serde_yaml::from_str::<Data3>(yaml); // Ok
    println!("{:?}", dat);
    let dat = serde_yaml::from_str::<Data4>(yaml); // Ok
    println!("{:?}", dat);

    let yaml = r#"
    env:
      foo: 123
    "#;

    println!();
    let dat = serde_yaml::from_str::<Data1>(yaml); // Ok
    println!("{:?}", dat);
    let dat = serde_yaml::from_str::<Data2>(yaml); // Err?
    println!("{:?}", dat);
    let dat = serde_yaml::from_str::<Data3>(yaml); // Err?
    println!("{:?}", dat);
    let dat = serde_yaml::from_str::<Data4>(yaml); // Err?
    println!("{:?}", dat);
}
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant