mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(serde_v8): support #[serde(default)] (#13300)
This commit is contained in:
parent
59f0eafd19
commit
12423e16b7
2 changed files with 37 additions and 47 deletions
|
@ -375,7 +375,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
|
|||
// Regular struct
|
||||
let obj = v8::Local::<v8::Object>::try_from(self.input)
|
||||
.map_err(|_| Error::ExpectedObject)?;
|
||||
let map = ObjectAccess {
|
||||
let struct_access = StructAccess {
|
||||
fields,
|
||||
obj,
|
||||
pos: 0,
|
||||
|
@ -383,7 +383,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
|
|||
_cache: None,
|
||||
};
|
||||
|
||||
visitor.visit_map(map)
|
||||
visitor.visit_seq(struct_access)
|
||||
}
|
||||
|
||||
/// To be compatible with `serde-json`, we expect enums to be:
|
||||
|
@ -511,7 +511,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'_, '_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
struct ObjectAccess<'a, 'b, 's> {
|
||||
struct StructAccess<'a, 'b, 's> {
|
||||
obj: v8::Local<'a, v8::Object>,
|
||||
scope: &'b mut v8::HandleScope<'s>,
|
||||
fields: &'static [&'static str],
|
||||
|
@ -519,57 +519,31 @@ struct ObjectAccess<'a, 'b, 's> {
|
|||
_cache: Option<&'b mut KeyCache>,
|
||||
}
|
||||
|
||||
fn str_deserializer(s: &str) -> de::value::StrDeserializer<Error> {
|
||||
de::IntoDeserializer::into_deserializer(s)
|
||||
}
|
||||
|
||||
impl<'de, 'a, 'b, 's> de::MapAccess<'de> for ObjectAccess<'a, 'b, 's> {
|
||||
impl<'de> de::SeqAccess<'de> for StructAccess<'_, '_, '_> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_key_seed<K: de::DeserializeSeed<'de>>(
|
||||
fn next_element_seed<T: de::DeserializeSeed<'de>>(
|
||||
&mut self,
|
||||
seed: K,
|
||||
) -> Result<Option<K::Value>> {
|
||||
Ok(match self.fields.get(self.pos) {
|
||||
Some(&field) => Some(seed.deserialize(str_deserializer(field))?),
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn next_value_seed<V: de::DeserializeSeed<'de>>(
|
||||
&mut self,
|
||||
seed: V,
|
||||
) -> Result<V::Value> {
|
||||
if self.pos >= self.fields.len() {
|
||||
return Err(Error::LengthMismatch);
|
||||
}
|
||||
let field = self.fields[self.pos];
|
||||
self.pos += 1;
|
||||
let key = v8_struct_key(self.scope, field).into();
|
||||
let v8_val = self.obj.get(self.scope, key).unwrap();
|
||||
let mut deserializer = Deserializer::new(self.scope, v8_val, None);
|
||||
seed.deserialize(&mut deserializer)
|
||||
}
|
||||
|
||||
fn next_entry_seed<
|
||||
K: de::DeserializeSeed<'de>,
|
||||
V: de::DeserializeSeed<'de>,
|
||||
>(
|
||||
&mut self,
|
||||
kseed: K,
|
||||
vseed: V,
|
||||
) -> Result<Option<(K::Value, V::Value)>> {
|
||||
seed: T,
|
||||
) -> Result<Option<T::Value>> {
|
||||
if self.pos >= self.fields.len() {
|
||||
return Ok(None);
|
||||
}
|
||||
let field = self.fields[self.pos];
|
||||
|
||||
let pos = self.pos;
|
||||
self.pos += 1;
|
||||
Ok(Some((kseed.deserialize(str_deserializer(field))?, {
|
||||
let key = v8_struct_key(self.scope, field).into();
|
||||
let v8_val = self.obj.get(self.scope, key).unwrap();
|
||||
let mut deserializer = Deserializer::new(self.scope, v8_val, None);
|
||||
vseed.deserialize(&mut deserializer)?
|
||||
})))
|
||||
|
||||
let field = self.fields[pos];
|
||||
let key = v8_struct_key(self.scope, field).into();
|
||||
let val = self.obj.get(self.scope, key).unwrap();
|
||||
let mut deserializer = Deserializer::new(self.scope, val, None);
|
||||
match seed.deserialize(&mut deserializer) {
|
||||
Ok(val) => Ok(Some(val)),
|
||||
// Fallback to Ok(None) for #[serde(Default)] at cost of error quality ...
|
||||
// TODO(@AaronO): double check that there's no better solution
|
||||
Err(_) if val.is_undefined() => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -271,3 +271,19 @@ detest!(de_bigint_i64, i64, "BigInt(-(2**59))", -(1 << 59));
|
|||
|
||||
defail!(defail_struct, MathOp, "123", |e| e
|
||||
== Err(Error::ExpectedObject));
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
pub struct SomeThing {
|
||||
pub a: String,
|
||||
#[serde(default)]
|
||||
pub b: String,
|
||||
}
|
||||
detest!(
|
||||
de_struct_defaults,
|
||||
SomeThing,
|
||||
"({ a: 'hello' })",
|
||||
SomeThing {
|
||||
a: "hello".into(),
|
||||
b: "".into()
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue