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

Field aliases do not work in combination with flatten #1504

Closed
alex-berger opened this issue Apr 9, 2019 · 9 comments · Fixed by #2387
Closed

Field aliases do not work in combination with flatten #1504

alex-berger opened this issue Apr 9, 2019 · 9 comments · Fixed by #2387

Comments

@alex-berger
Copy link

Field aliases as introduced in #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(())
}
@emilio
Copy link

emilio commented May 4, 2019

I just got bitten by this too.

@dtolnay
Copy link
Member

dtolnay commented May 4, 2019

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

@emilio
Copy link

emilio commented May 4, 2019

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

emilio added a commit to emilio/serde that referenced this issue May 4, 2019
emilio added a commit to emilio/serde that referenced this issue May 4, 2019
The issue is that FlatStructAccess has no access to the aliases of the struct
it's deserializing.

Ideally we'd try to serialize the key rather than checking whether we're going
to use it before-hand, then actually take the value out, but that happens to be
tricky with the current seed API.

So we need to somehow get the aliased names back to FlatStructAccess. Introduce
a serialize_struct-like API that takes them in a backwards-compatible way. For
parallelism, and since we also support aliases on enum variants, also extend the
struct_variant API in a similar way. I'm open to better ways to fix it, but I
can't think of any other that isn't a breaking change...

Fixes serde-rs#1504.
emilio added a commit to emilio/serde that referenced this issue May 4, 2019
The issue is that FlatStructAccess has no access to the aliases of the struct
it's deserializing.

Ideally we'd try to serialize the key rather than checking whether we're going
to use it before-hand, then actually take the value out, but that happens to be
tricky with the current seed API.

So we need to somehow get the aliased names back to FlatStructAccess. Introduce
a serialize_struct-like API that takes them in a backwards-compatible way. For
parallelism, and since we also support aliases on enum variants, also extend the
struct_variant API in a similar way. I'm open to better ways to fix it, but I
can't think of any other that isn't a breaking change...

Fixes serde-rs#1504.
emilio added a commit to emilio/aemet-visualizer that referenced this issue May 4, 2019
This is gonna be useful to parse aggregate data.

Patch with serde-rs/serde#1519
to work-around / fix serde-rs/serde#1504.

That bound is needed due to deserialize_with, it's kind-of unfortunate that it
cannot be inferred.
@Jezza
Copy link

Jezza commented Oct 12, 2019

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
Copy link

Jezza commented Oct 12, 2019

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.

@SciStarter

This comment has been minimized.

@rawkode

This comment has been minimized.

@CrashAndSideburns

This comment has been minimized.

CrashAndSideburns pushed a commit to CrashAndSideburns/rust-lichess-wrapper that referenced this issue Jan 9, 2022
But what if... I were to rename the "name" field to "username" so that I can use it for Top10s and disguise it as "name" using an alias? Delightfully devilish, Seymour...

Hacky fix to get around serde-rs/serde#1504. Alias and name should be swapped once the issue is fixed. Also I forgot to make a field public for some reason.
jhoobergs pushed a commit to jhoobergs/serde that referenced this issue Jan 21, 2022
jhoobergs pushed a commit to jhoobergs/serde that referenced this issue Jan 21, 2022
The issue is that FlatStructAccess has no access to the aliases of the struct
it's deserializing.

Ideally we'd try to serialize the key rather than checking whether we're going
to use it before-hand, then actually take the value out, but that happens to be
tricky with the current seed API.

So we need to somehow get the aliased names back to FlatStructAccess. Introduce
a serialize_struct-like API that takes them in a backwards-compatible way. For
parallelism, and since we also support aliases on enum variants, also extend the
struct_variant API in a similar way. I'm open to better ways to fix it, but I
can't think of any other that isn't a breaking change...

Fixes serde-rs#1504.
@ctron

This comment has been minimized.

@serde-rs serde-rs locked and limited conversation to collaborators Jan 24, 2022
jhoobergs pushed a commit to jhoobergs/serde that referenced this issue Oct 2, 2022
The issue is that FlatStructAccess has no access to the aliases of the struct
it's deserializing.

Ideally we'd try to serialize the key rather than checking whether we're going
to use it before-hand, then actually take the value out, but that happens to be
tricky with the current seed API.

So we need to somehow get the aliased names back to FlatStructAccess. Introduce
a serialize_struct-like API that takes them in a backwards-compatible way. For
parallelism, and since we also support aliases on enum variants, also extend the
struct_variant API in a similar way. I'm open to better ways to fix it, but I
can't think of any other that isn't a breaking change...

Fixes serde-rs#1504.
bebecue added a commit to bebecue/serde that referenced this issue Mar 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.