serde icon indicating copy to clipboard operation
serde copied to clipboard

Field aliases do not work in combination with `flatten`

Open alex-berger opened this issue 7 years ago • 9 comments

Field aliases as introduced in https://github.com/serde-rs/serde/pull/1458 do not work when deserializing "flattened" structures.

Expected behavior

Field aliases should work when deserializing "flattened" structures.

Observed behavior

Field aliases do not work when deserializing "flattened" structures.

How to reproduce

The following code can be used to reproduce the problem, also available as Rust Playground snippet here.

use serde::{Deserialize, Serialize};
use serde_json;

#[derive(Serialize, Deserialize)]
pub struct A {
    #[serde(rename = "y", alias = "z")]
    x: i64,
}

#[derive(Serialize, Deserialize)]
pub struct B {
    #[serde(flatten)]
    a: A,
}

fn main() -> Result<(),Box<std::error::Error>> {
     let i = r#"{ "z": 12 }"#; // using r#"{ "y": 12 }"# will work.
     let b: B = serde_json::from_str(i)?;
     assert_eq!(b.a.x,12);
     Ok(())
}

alex-berger avatar Apr 09 '19 07:04 alex-berger

I just got bitten by this too.

emilio avatar May 04 '19 18:05 emilio

This is a bug -- I would accept a PR to fix this.

dtolnay avatar May 04 '19 18:05 dtolnay

I'll try to give it a shot, but first time poking at serde_derive, so no promises :)

emilio avatar May 04 '19 18:05 emilio

Yeah, I just got bit by this too.
I was using variants, so I thought it was related to that.
I can take a try at fixing this if there's been no progress.

use serde::Deserialize;
use serde_json::from_str;

#[derive(Debug, Deserialize)]
struct Value {
	#[serde(flatten)]
	data: Ser,
}

#[derive(Debug, Deserialize)]
enum Ser {
	#[serde(rename = "var", alias = "def")]
	Variant(u8)
}

fn main() {
	let input = r#"{ "def": 0 }"#;
	println!("{:?}", from_str::<Ser>(input).unwrap());
	println!("{:?}", from_str::<Value>(input).unwrap());
}

Jezza avatar Oct 12 '19 00:10 Jezza

After hunting around, I found the issue.

We pass an array of valid variants directly into the deserialize_enum.
The aliases aren't counted as variants, and so aren't added to the list.
We could add the aliases to the generated array, but I don't know if that might break other things.

I'm open to ideas.

EDIT: I forgot that structs have this issue as well. We pass in an array of field names (non-aliased).

We could add the aliased names to the arrays, and then internally, when it actually goes to deserialise it, sort out which one to use, etc, like normal.

Jezza avatar Oct 12 '19 02:10 Jezza

Two years later, I just got bitten by this bug. A fix would be very appreciated.

SciStarter avatar Sep 07 '21 10:09 SciStarter

Just got bitten by this too 😭

rawkode avatar Sep 08 '21 20:09 rawkode

Was also just bitten by this.

CrashAndSideburns avatar Jan 09 '22 03:01 CrashAndSideburns

I just ran into the same issue.

ctron avatar Jan 24 '22 10:01 ctron