Repository: diesel-rs/diesel
File: diesel/src/pg/expression/functions.rs (Rust)

Code before:
    /// #     use diesel::dsl::jsonb_object_with_keys_and_values;
    /// #     use diesel::sql_types::{Array, Nullable, Text};
    /// #     use serde_json::Value;
    /// #     let connection = &mut establish_connection();
    /// let jsonb = diesel::select(jsonb_object_with_keys_and_values::<Array<Text>, _, _>(
    ///             vec!["hello","John"],vec!["world","Doe"]))
    ///             .get_result::<Value>(connection)?;
    /// let expected:Value = serde_json::json!({"hello":"world","John":"Doe"});
    /// assert_eq!(expected,jsonb);
    ///
    /// let jsonb = diesel::select(jsonb_object_with_keys_and_values::<Nullable<Array<Text>>, _, _>(
    ///             Some(vec!["hello","John"]),None::<Vec<String>>))
    ///             .get_result::<Option<Value>>(connection)?;
    /// assert_eq!(None::<Value>,jsonb);
    ///
    /// let empty: Vec<String> = Vec::new();
    /// let jsonb = diesel::select(jsonb_object_with_keys_and_values::<Array<Text>, _, _>(
    ///             vec!["hello","John"],empty))
    ///             .get_result::<Value>(connection);
    /// assert!(jsonb.is_err());
    ///
    /// #     Ok(())
    /// # }
    /// ```
    #[sql_name = "jsonb_object"]
    fn jsonb_object_with_keys_and_values<Arr: TextArrayOrNullableTextArray + MaybeNullableValue<Jsonb>>(
        keys: Arr, values: Arr
    ) -> Arr::Out;
}


Review comment (suggestion):
I think we need to use the `CombinedNullableValue trait that I've introduced in https://github.com/diesel-rs/diesel/commit/b488df40b6ddbcbbf0e35225badc90513cabcc4e. The signature should be essentially the same as there.

Code after:
    /// ```
    #[sql_name = "json_object"]
    fn json_object_with_keys_and_values<
        Arr1: TextArrayOrNullableTextArray + SingleValue,
        Arr2: TextArrayOrNullableTextArray + CombinedNullableValue<Arr1, Json>,
    >(
        keys: Arr1,
        values: Arr2,
    ) -> Arr2::Out;
}

#[cfg(feature = "postgres_backend")]
define_sql_function! {
    /// Returns the type of the top-level json value as a text-string
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     #[cfg(feature = "serde_json")]
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # #[cfg(feature = "serde_json")]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::dsl::json_typeof;
    /// #     use serde_json::{json, Value};
    /// #     use diesel::sql_types::{Json, Nullable};
    /// #     let connection = &mut establish_connection();
    /// let result = diesel::select(json_typeof::<Json, _>(json!({"a": "b", "c": 1})))
    ///     .get_result::<String>(connection)?;
    ///
    /// assert_eq!("object".to_string(), result);
    ///
    /// let result = diesel::select(json_typeof::<Json, _>(json!([1,2,3])))
    ///     .get_result::<String>(connection)?;
    ///
    /// assert_eq!("array".to_string(), result);
    ///
    /// let result = diesel::select(json_typeof::<Json, _>(json!("abc")))
    ///     .get_result::<String>(connection)?;
    ///
    /// assert_eq!("string".to_string(), result);
    ///
    /// let result = diesel::select(json_typeof::<Json, _>(json!(-123.4)))
    ///     .get_result::<String>(connection)?;
    ///
    /// assert_eq!("number".to_string(), result);
    ///