На самом деле кажется, что использование специального десериализатора внутри Vec (или карты, и т. Д.) - это открытый вопрос о serde, который длился чуть больше года (на момент написания): https://github.com/serde-rs/serde/issues/723
Я полагаю, что решение состоит в том, чтобы написать собственный десериализатор для f64
(что нормально), а также все, что использует f64
в качестве субтитра (например, Vec<f64>
, HashMap<K, f64>
и т. Д.).К сожалению, не похоже, что эти вещи являются составными, так как реализации этих методов выглядят как
deserialize<'de, D>(deserializer: D) -> Result<Vec<f64>, D::Error>
where D: Deserializer<'de> { /* snip */ }
, и когда у вас есть десериализатор, вы можете взаимодействовать с ним только через посетителей.
Длинная историяКороче говоря, я в конечном итоге получил это работает, но, похоже, много кода, который не должен быть необходим.Публикуйте это здесь в надежде, что (а) кто-то знает, как это исправить, или (б) это действительно так, и это ответ кому-то пригодится.Я потратил целый день, усердно читая документы и делая предположения проб и ошибок, так что, возможно, это будет полезно для кого-то еще.Функции (de)serialize_float(s)
должны использоваться с соответствующим #[serde( (de)serialize_with="etc." )]
над именем поля.
use serde::de::{self, SeqAccess, Visitor};
use serde::ser::SerializeSeq;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
type Float = f64;
const NAN: Float = std::f64::NAN;
struct NiceFloat(Float);
impl Serialize for NiceFloat {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serialize_float(&self.0, serializer)
}
}
pub fn serialize_float<S>(x: &Float, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if x.is_nan() {
serializer.serialize_str("NaN")
} else {
serializer.serialize_f64(*x)
}
}
pub fn serialize_floats<S>(floats: &[Float], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(floats.len()))?;
for f in floats {
seq.serialize_element(&NiceFloat(*f))?;
}
seq.end()
}
struct FloatDeserializeVisitor;
impl<'de> Visitor<'de> for FloatDeserializeVisitor {
type Value = Float;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a float or the string \"NaN\"")
}
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v as Float)
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v as Float)
}
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v as Float)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v as Float)
}
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v as Float)
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v as Float)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == "NaN" {
Ok(NAN)
} else {
Err(E::invalid_value(de::Unexpected::Str(v), &self))
}
}
}
struct NiceFloatDeserializeVisitor;
impl<'de> Visitor<'de> for NiceFloatDeserializeVisitor {
type Value = NiceFloat;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a float or the string \"NaN\"")
}
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(NiceFloat(v as Float))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(NiceFloat(v as Float))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == "NaN" {
Ok(NiceFloat(NAN))
} else {
Err(E::invalid_value(de::Unexpected::Str(v), &self))
}
}
}
pub fn deserialize_float<'de, D>(deserializer: D) -> Result<Float, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(FloatDeserializeVisitor)
}
impl<'de> Deserialize<'de> for NiceFloat {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw = deserialize_float(deserializer)?;
Ok(NiceFloat(raw))
}
}
pub struct VecDeserializeVisitor<T>(std::marker::PhantomData<T>);
impl<'de, T> Visitor<'de> for VecDeserializeVisitor<T>
where
T: Deserialize<'de> + Sized,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("A sequence of floats or \"NaN\" string values")
}
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
where
S: SeqAccess<'de>,
{
let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
while let Some(value) = seq.next_element()? {
out.push(value);
}
Ok(out)
}
}
pub fn deserialize_floats<'de, D>(deserializer: D) -> Result<Vec<Float>, D::Error>
where
D: Deserializer<'de>,
{
let visitor: VecDeserializeVisitor<NiceFloat> = VecDeserializeVisitor(std::marker::PhantomData);
let seq: Vec<NiceFloat> = deserializer.deserialize_seq(visitor)?;
let raw: Vec<Float> = seq.into_iter().map(|nf| nf.0).collect::<Vec<Float>>();
Ok(raw)
}