From 83f59ba0bdcd5847eaff15ad8c39f6ca549403bb Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Mon, 7 Aug 2023 10:55:13 +0200 Subject: [PATCH] deserialize number or string --- ffplayout-api/src/db/models.rs | 46 ++++++++++++++++++++++++++++- ffplayout-engine/src/rpc/server.rs | 47 ++++++++++++++++++++---------- ffplayout-frontend | 2 +- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/ffplayout-api/src/db/models.rs b/ffplayout-api/src/db/models.rs index bc7e5247..a1984625 100644 --- a/ffplayout-api/src/db/models.rs +++ b/ffplayout-api/src/db/models.rs @@ -1,4 +1,8 @@ -use serde::{Deserialize, Serialize}; +use regex::Regex; +use serde::{ + de::{self, Visitor}, + Deserialize, Serialize, +}; #[derive(Debug, Deserialize, Serialize, sqlx::FromRow)] pub struct User { @@ -49,15 +53,55 @@ pub struct TextPreset { pub text: String, pub x: String, pub y: String, + #[serde(deserialize_with = "deserialize_number_or_string")] pub fontsize: String, + #[serde(deserialize_with = "deserialize_number_or_string")] pub line_spacing: String, pub fontcolor: String, pub r#box: String, pub boxcolor: String, + #[serde(deserialize_with = "deserialize_number_or_string")] pub boxborderw: String, + #[serde(deserialize_with = "deserialize_number_or_string")] pub alpha: String, } +/// Deserialize number or string +pub fn deserialize_number_or_string<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + struct StringOrNumberVisitor; + + impl<'de> Visitor<'de> for StringOrNumberVisitor { + type Value = String; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a string or a number") + } + + fn visit_str(self, value: &str) -> Result { + let re = Regex::new(r"0,([0-9]+)").unwrap(); + let clean_string = re.replace_all(value, "0.$1").to_string(); + Ok(clean_string) + } + + fn visit_u64(self, value: u64) -> Result { + Ok(value.to_string()) + } + + fn visit_i64(self, value: i64) -> Result { + Ok(value.to_string()) + } + + fn visit_f64(self, value: f64) -> Result { + Ok(value.to_string()) + } + } + + deserializer.deserialize_any(StringOrNumberVisitor) +} + #[derive(Debug, Deserialize, Serialize, sqlx::FromRow)] pub struct Channel { #[serde(skip_deserializing)] diff --git a/ffplayout-engine/src/rpc/server.rs b/ffplayout-engine/src/rpc/server.rs index df209a8d..2a838757 100644 --- a/ffplayout-engine/src/rpc/server.rs +++ b/ffplayout-engine/src/rpc/server.rs @@ -6,8 +6,11 @@ extern crate serde_json; extern crate tiny_http; use futures::executor::block_on; -use serde::{Deserialize, Serialize}; -use serde_json::{json, Map, Value}; +use serde::{ + de::{self, Visitor}, + Deserialize, Serialize, +}; +use serde_json::{json, Map}; use simplelog::*; use std::collections::HashMap; use std::io::{Cursor, Error as IoError}; @@ -41,28 +44,40 @@ struct TextFilter { boxborderw: Option, } -fn deserialize_number_or_string<'de, D>(deserializer: D) -> Result, D::Error> +/// Deserialize number or string +pub fn deserialize_number_or_string<'de, D>(deserializer: D) -> Result, D::Error> where D: serde::Deserializer<'de>, { - let value: Value = Deserialize::deserialize(deserializer)?; - match value { - Value::Number(num) => { - if let Some(number) = num.as_i64() { - Ok(Some(number.to_string())) - } else if let Some(number) = num.as_f64() { - Ok(Some(number.to_string())) - } else { - Err(serde::de::Error::custom("Invalid number format")) - } + struct StringOrNumberVisitor; + + impl<'de> Visitor<'de> for StringOrNumberVisitor { + type Value = Option; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a string or a number") } - Value::String(string) => { + + fn visit_str(self, value: &str) -> Result { let re = Regex::new(r"0,([0-9]+)").unwrap(); - let clean_string = re.replace_all(&string, "0.$1").to_string(); + let clean_string = re.replace_all(value, "0.$1").to_string(); Ok(Some(clean_string)) } - _ => Err(serde::de::Error::custom("Invalid value type")), + + fn visit_u64(self, value: u64) -> Result { + Ok(Some(value.to_string())) + } + + fn visit_i64(self, value: i64) -> Result { + Ok(Some(value.to_string())) + } + + fn visit_f64(self, value: f64) -> Result { + Ok(Some(value.to_string())) + } } + + deserializer.deserialize_any(StringOrNumberVisitor) } impl fmt::Display for TextFilter { diff --git a/ffplayout-frontend b/ffplayout-frontend index 6f898d79..b5aa06a5 160000 --- a/ffplayout-frontend +++ b/ffplayout-frontend @@ -1 +1 @@ -Subproject commit 6f898d7916142fb78b403f4ebfdb4e698dca50cf +Subproject commit b5aa06a504df7e5d0c87c73a4093eb841e003048