이 솔루션은 Serde 1.0에서 작동합니다.
visitor.visit_newtype_struct
을 newtypes의 역 직렬화를 호출해야하는 사람이 필요했기 때문에 내가 찾은 방식으로 사용자 지정 deserializer를 작성해야했지만, 그렇게하는 것은 serde에 내장되어있는 것처럼 보이지 않습니다. (나는 ValueDeserializer
계열과 같은 것을 기대하고 있었다.)
독립된 예가 아래에있다. SomeStruct
은 두 입력에 대해 올바르게 직렬화 해제됩니다. 하나는 값이 JSON 문자열 배열이고 다른 하나는 문자열입니다.
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
use std::fmt;
use std::marker::PhantomData;
use serde::de;
use serde::de::{Deserialize, Deserializer};
#[derive(Deserialize, Debug, Clone)]
pub struct Parent {
#[serde(deserialize_with = "string_or_seq_string")]
pub strings: Vec<String>,
}
fn main() {
let list_of_strings: Parent = serde_json::from_str(r#"{ "strings": ["value1", "value2"] }"#).unwrap();
println!("list of strings: {:?}", list_of_strings);
// Prints:
// list of strings: Parent { strings: ["value1", "value2"] }
let single_string: Parent = serde_json::from_str(r#"{ "strings": "value" }"#).unwrap();
println!("single string: {:?}", single_string);
// Prints:
// single string: Parent { strings: ["value"] }
}
fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where D: Deserializer<'de>
{
struct StringOrVec(PhantomData<Vec<String>>);
impl<'de> de::Visitor<'de> for StringOrVec {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or list of strings")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where E: de::Error
{
Ok(vec![value.to_owned()])
}
fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
where S: de::SeqAccess<'de>
{
Deserialize::deserialize(de::value::SeqAccessDeserializer::new(visitor))
}
}
deserializer.deserialize_any(StringOrVec(PhantomData))
}
이 : 경우
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
fn main() {
#[derive(Debug, Deserialize)]
struct SomeStringNewType(String);
#[derive(Debug)]
struct SomeTypeWithCustomDeserializeFromStr(String);
impl<'de> ::serde::Deserialize<'de> for SomeTypeWithCustomDeserializeFromStr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: ::serde::Deserializer<'de> {
struct Visitor;
impl<'de> ::serde::de::Visitor<'de> for Visitor {
type Value = SomeTypeWithCustomDeserializeFromStr;
fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: ::serde::de::Error {
Ok(SomeTypeWithCustomDeserializeFromStr(v.to_string() + " custom"))
}
}
deserializer.deserialize_any(Visitor)
}
}
#[derive(Debug, Deserialize)]
struct SomeStruct {
#[serde(deserialize_with = "deserialize_string_or_seq_string")]
field1: Vec<SomeStringNewType>,
#[serde(deserialize_with = "deserialize_string_or_seq_string")]
field2: Vec<SomeTypeWithCustomDeserializeFromStr>,
}
let x: SomeStruct = ::serde_json::from_str(r#"{ "field1": ["a"], "field2": ["b"] }"#).unwrap();
println!("{:?}", x);
assert_eq!(x.field1[0].0, "a");
assert_eq!(x.field2[0].0, "b custom");
let x: SomeStruct = ::serde_json::from_str(r#"{ "field1": "c", "field2": "d" }"#).unwrap();
println!("{:?}", x);
assert_eq!(x.field1[0].0, "c");
assert_eq!(x.field2[0].0, "d custom");
}
/// Deserializes a string or a sequence of strings into a vector of the target type.
pub fn deserialize_string_or_seq_string<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
where T: ::serde::Deserialize<'de>, D: ::serde::Deserializer<'de> {
struct Visitor<T>(::std::marker::PhantomData<T>);
impl<'de, T> ::serde::de::Visitor<'de> for Visitor<T>
where T: ::serde::Deserialize<'de> {
type Value = Vec<T>;
fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "a string or sequence of strings")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: ::serde::de::Error {
let value = {
// Try parsing as a newtype
let deserializer = StringNewTypeStructDeserializer(v, ::std::marker::PhantomData);
::serde::Deserialize::deserialize(deserializer)
}.or_else(|_: E| {
// Try parsing as a str
let deserializer = ::serde::de::IntoDeserializer::into_deserializer(v);
::serde::Deserialize::deserialize(deserializer)
})?;
Ok(vec![value])
}
fn visit_seq<A>(self, visitor: A) -> Result<Self::Value, A::Error>
where A: ::serde::de::SeqAccess<'de> {
::serde::Deserialize::deserialize(::serde::de::value::SeqAccessDeserializer::new(visitor))
}
}
deserializer.deserialize_any(Visitor(::std::marker::PhantomData))
}
// Tries to deserialize the given string as a newtype
struct StringNewTypeStructDeserializer<'a, E>(&'a str, ::std::marker::PhantomData<E>);
impl<'de, 'a, E> ::serde::Deserializer<'de> for StringNewTypeStructDeserializer<'a, E> where E: ::serde::de::Error {
type Error = E;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: ::serde::de::Visitor<'de> {
visitor.visit_newtype_struct(self)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: ::serde::de::Visitor<'de> {
// Called by newtype visitor
visitor.visit_str(self.0)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map
struct enum identifier ignored_any
}
}
이 질문으로'SomeStringNewType (문자열)'또는'SomeTypeWithCustomDeserializeFromStr (String)를'역 직렬화하지 않습니다 필요합니다. – Arnavion
죄송합니다.'SomeStringNewType'은'String'으로 작업 할 수 없기 때문에 해결 방법의 일부였습니다. 네가 괜찮 으면, 나는 적어도이 제목을 찾았 기 때문에이 질문을 접하게 되었기 때문에 나는 여전히이 해답을 가지고있다. 나는 이것이 단순한'String'을 원한다는 일반적인 형식을위한 답을 업데이트했다. – Pit
예, 사용자가 String을 직접 deserialize하려는 경우에 대한 대답이 좋습니다. 삭제할 이유가 없습니다. – Arnavion