diff --git a/meilisearch-http/src/helpers/meilisearch.rs b/meilisearch-http/src/helpers/meilisearch.rs index b5d772157..8079f7168 100644 --- a/meilisearch-http/src/helpers/meilisearch.rs +++ b/meilisearch-http/src/helpers/meilisearch.rs @@ -1,4 +1,4 @@ -use crate::routes::setting::{RankingOrdering, SettingBody}; +use crate::routes::setting::{RankingOrdering, Setting}; use indexmap::IndexMap; use log::{error, warn}; use meilisearch_core::criterion::*; @@ -299,7 +299,7 @@ impl<'a> SearchBuilder<'a> { ) -> Result>, Error> { let current_settings = match self.index.main.customs(reader).unwrap() { Some(bytes) => bincode::deserialize(bytes).unwrap(), - None => SettingBody::default(), + None => Setting::default(), }; let ranking_rules = ¤t_settings.ranking_rules; diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs index 5793fcf47..8415aedeb 100644 --- a/meilisearch-http/src/routes/setting.rs +++ b/meilisearch-http/src/routes/setting.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use http::StatusCode; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Deserializer}; use tide::response::IntoResponse; use tide::{Context, Response}; @@ -11,9 +11,9 @@ use crate::models::token::ACL::*; use crate::routes::document::IndexUpdateResponse; use crate::Data; -#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct SettingBody { +pub struct Setting { pub ranking_order: Option, pub distinct_field: Option, pub ranking_rules: Option, @@ -39,12 +39,31 @@ pub async fn get(ctx: Context) -> SResult { let settings = match index.main.customs(&reader).unwrap() { Some(bytes) => bincode::deserialize(bytes).unwrap(), - None => SettingBody::default(), + None => Setting::default(), }; Ok(tide::response::json(settings)) } +#[derive(Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct SettingBody { + #[serde(default, deserialize_with = "deserialize_some")] + pub ranking_order: Option>, + #[serde(default, deserialize_with = "deserialize_some")] + pub distinct_field: Option>, + #[serde(default, deserialize_with = "deserialize_some")] + pub ranking_rules: Option>, +} + +// Any value that is present is considered Some value, including null. +fn deserialize_some<'de, T, D>(deserializer: D) -> Result, D::Error> + where T: Deserialize<'de>, + D: Deserializer<'de> +{ + Deserialize::deserialize(deserializer).map(Some) +} + pub async fn update(mut ctx: Context) -> SResult { ctx.is_allowed(SettingsWrite)?; @@ -58,19 +77,19 @@ pub async fn update(mut ctx: Context) -> SResult { let mut current_settings = match index.main.customs(&reader).unwrap() { Some(bytes) => bincode::deserialize(bytes).unwrap(), - None => SettingBody::default(), + None => Setting::default(), }; if let Some(ranking_order) = settings.ranking_order { - current_settings.ranking_order = Some(ranking_order); + current_settings.ranking_order = ranking_order; } if let Some(distinct_field) = settings.distinct_field { - current_settings.distinct_field = Some(distinct_field); + current_settings.distinct_field = distinct_field; } if let Some(ranking_rules) = settings.ranking_rules { - current_settings.ranking_rules = Some(ranking_rules); + current_settings.ranking_rules = ranking_rules; } let bytes = bincode::serialize(¤t_settings).unwrap();