mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -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
|
// Regular struct
|
||||||
let obj = v8::Local::<v8::Object>::try_from(self.input)
|
let obj = v8::Local::<v8::Object>::try_from(self.input)
|
||||||
.map_err(|_| Error::ExpectedObject)?;
|
.map_err(|_| Error::ExpectedObject)?;
|
||||||
let map = ObjectAccess {
|
let struct_access = StructAccess {
|
||||||
fields,
|
fields,
|
||||||
obj,
|
obj,
|
||||||
pos: 0,
|
pos: 0,
|
||||||
|
@ -383,7 +383,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
|
||||||
_cache: None,
|
_cache: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
visitor.visit_map(map)
|
visitor.visit_seq(struct_access)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To be compatible with `serde-json`, we expect enums to be:
|
/// 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>,
|
obj: v8::Local<'a, v8::Object>,
|
||||||
scope: &'b mut v8::HandleScope<'s>,
|
scope: &'b mut v8::HandleScope<'s>,
|
||||||
fields: &'static [&'static str],
|
fields: &'static [&'static str],
|
||||||
|
@ -519,57 +519,31 @@ struct ObjectAccess<'a, 'b, 's> {
|
||||||
_cache: Option<&'b mut KeyCache>,
|
_cache: Option<&'b mut KeyCache>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn str_deserializer(s: &str) -> de::value::StrDeserializer<Error> {
|
impl<'de> de::SeqAccess<'de> for StructAccess<'_, '_, '_> {
|
||||||
de::IntoDeserializer::into_deserializer(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a, 'b, 's> de::MapAccess<'de> for ObjectAccess<'a, 'b, 's> {
|
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn next_key_seed<K: de::DeserializeSeed<'de>>(
|
fn next_element_seed<T: de::DeserializeSeed<'de>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
seed: K,
|
seed: T,
|
||||||
) -> Result<Option<K::Value>> {
|
) -> Result<Option<T::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)>> {
|
|
||||||
if self.pos >= self.fields.len() {
|
if self.pos >= self.fields.len() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let field = self.fields[self.pos];
|
|
||||||
|
let pos = self.pos;
|
||||||
self.pos += 1;
|
self.pos += 1;
|
||||||
Ok(Some((kseed.deserialize(str_deserializer(field))?, {
|
|
||||||
let key = v8_struct_key(self.scope, field).into();
|
let field = self.fields[pos];
|
||||||
let v8_val = self.obj.get(self.scope, key).unwrap();
|
let key = v8_struct_key(self.scope, field).into();
|
||||||
let mut deserializer = Deserializer::new(self.scope, v8_val, None);
|
let val = self.obj.get(self.scope, key).unwrap();
|
||||||
vseed.deserialize(&mut deserializer)?
|
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
|
defail!(defail_struct, MathOp, "123", |e| e
|
||||||
== Err(Error::ExpectedObject));
|
== 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