음, 여기 그 일을하는 한 가지 방법이다 : 직렬화에서 우리는 자동으로 생성 디시리얼라이저를 다시 사용할 수
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Debug)]
enum AgeOrError {
Age(MyAge),
Error(MyError),
}
impl serde::Serialize for AgeOrError {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
&AgeOrError::Age(ref my_age) => serializer.serialize_some(my_age),
&AgeOrError::Error(ref my_error) => serializer.serialize_some(my_error),
}
}
}
enum AgeOrErrorField {
Age,
Name,
Error,
}
impl serde::Deserialize for AgeOrErrorField {
fn deserialize<D>(deserializer: D) -> Result<AgeOrErrorField, D::Error>
where D: serde::Deserializer
{
struct AgeOrErrorFieldVisitor;
impl serde::de::Visitor for AgeOrErrorFieldVisitor {
type Value = AgeOrErrorField;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "age or error")
}
fn visit_str<E>(self, value: &str) -> Result<AgeOrErrorField, E>
where E: serde::de::Error
{
Ok(match value {
"age" => AgeOrErrorField::Age,
"name" => AgeOrErrorField::Name,
"error" => AgeOrErrorField::Error,
_ => panic!("Unexpected field name: {}", value),
})
}
}
deserializer.deserialize(AgeOrErrorFieldVisitor)
}
}
impl serde::Deserialize for AgeOrError {
fn deserialize<D>(deserializer: D) -> Result<AgeOrError, D::Error>
where D: serde::Deserializer
{
deserializer.deserialize_map(AgeOrErrorVisitor)
}
}
struct AgeOrErrorVisitor;
impl serde::de::Visitor for AgeOrErrorVisitor {
type Value = AgeOrError;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "age or error")
}
fn visit_map<V>(self, mut visitor: V) -> Result<AgeOrError, V::Error>
where V: serde::de::MapVisitor
{
let mut age: Option<i32> = None;
let mut name: Option<String> = None;
let mut error: Option<String> = None;
loop {
match try!(visitor.visit_key()) {
Some(AgeOrErrorField::Age) => age = try!(visitor.visit_value()),
Some(AgeOrErrorField::Name) => name = try!(visitor.visit_value()),
Some(AgeOrErrorField::Error) => error = try!(visitor.visit_value()),
None => break,
}
}
if let Some(error) = error {
Ok(AgeOrError::Error(MyError { error: error }))
} else {
Ok(AgeOrError::Age(MyAge {
age: age.expect("!age"),
name: name.expect("!name"),
}))
}
}
}
fn get_results(ages: &[i32]) -> Vec<AgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for &age in ages.iter() {
if age < 100 && age > 0 {
results.push(AgeOrError::Age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(AgeOrError::Error(MyError { error: format!("{} is invalid age", age) }));
}
}
results
}
pub fn main() {
let v = get_results(&[1, -6, 7]);
let serialized = serde_json::to_string(&v).expect("Can't serialize");
println!("serialized: {}", serialized);
let deserialized: Vec<AgeOrError> = serde_json::from_str(&serialized)
.expect("Can't deserialize");
println!("deserialized: {:?}", deserialized);
}
주 이유는
가) 직렬화 종류의 우리에게 필드를 스트리밍, 우리 peook을 문자열로 묶은 JSON 표현으로 변환 할 수 없으며 그것이 무엇인지 추측 할 수 없습니다.
b) Serde가 생성하는 serde::de::Visitor
구현에 액세스 할 수 없습니다.
또한 바로 가기와 panick
오류가 발생했습니다. 프로덕션 코드에서는 적절한 Serde 오류를 반환하는 것이 좋습니다.
또 다른 해결책은 다음과 같이 선택 모든 필드와 병합 된 구조를 확인하는 것입니다 :
이
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Debug)]
pub struct MyError {
error: String,
}
#[derive(Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAgeOrError {
#[serde(skip_serializing_if="Option::is_none")]
age: Option<i32>,
#[serde(skip_serializing_if="Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if="Option::is_none")]
error: Option<String>,
}
impl MyAgeOrError {
fn from_age(age: MyAge) -> MyAgeOrError {
MyAgeOrError {
age: Some(age.age),
name: Some(age.name),
error: None,
}
}
fn from_error(error: MyError) -> MyAgeOrError {
MyAgeOrError {
age: None,
name: None,
error: Some(error.error),
}
}
}
fn get_results(ages: &[i32]) -> Vec<MyAgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for &age in ages.iter() {
if age < 100 && age > 0 {
results.push(MyAgeOrError::from_age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(MyAgeOrError::from_error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
pub fn main() {
let v = get_results(&[1, -6, 7]);
let serialized = serde_json::to_string(&v).expect("Can't serialize");
println!("serialized: {}", serialized);
let deserialized: Vec<MyAgeOrError> = serde_json::from_str(&serialized)
.expect("Can't deserialize");
println!("deserialized: {:?}", deserialized);
}
가 녹 구조를 수 있기 때문에 나는이 일에 대한 신뢰도를 보장 할 것
(예)에 맞게 JSON의 레이아웃 그런 식으로 JSON 레이아웃이 Rust 코드로 문서화됩니다.
현재 일련 번호를 표시하십시오. –
@ker 그것은 무엇이든 검색하지 않습니다. 이것은 유효한 코드가 아닙니다. "MyError"및 "MyAge"는 호환 유형이 아니기 때문에 – user3384741
우 ... 대신 enum을 사용해 보셨나요? 문제를 해결하는 데는 백만 가지 방법이 있습니다. 솔루션에는 직접 작성해야하는 코드와 양이 있습니다. 정확한 출력 형식에 구속되어 있습니까? –