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

Code before:
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::dsl::json_strip_nulls;
    /// #     use diesel::sql_types::{Json, Nullable};
    /// #     use serde_json::{json, Value};
    /// #     let connection = &mut establish_connection();
    ///
    /// let result = diesel::select(json_strip_nulls::<Json, _>(json!({"hello": null})))
    ///     .get_result::<Value>(connection)?;
    /// let expected: Value = json!({});
    /// assert_eq!(result, expected);
    ///
    /// let result = diesel::select(json_strip_nulls::<Json, _>(json!([{"f1":1, "f2":null}, 2, null, 3])))
    ///     .get_result::<Value>(connection)?;
    /// let expected: Value = json!([{"f1":1}, 2, null, 3]);
    /// assert_eq!(result, expected);
    ///
    /// let result = diesel::select(json_strip_nulls::<Json, _>(json!(null)))
    ///     .get_result::<Value>(connection)?;
    /// let expected = json!(null);
    /// assert_eq!(result, expected);
    ///
    ///
    /// #     Ok(())
    /// # }
    /// ```
    fn json_strip_nulls<E: MaybeNullableValue<Json>>(json: E) -> E::Out;
}

define_sql_function! {
    /// Deletes all object fields that have null values from the given JSON value, recursively.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::dsl::jsonb_strip_nulls;
    /// #     use diesel::sql_types::{Jsonb, Nullable};
    /// #     use serde_json::{json, Value};
    /// #     let connection = &mut establish_connection();
    ///
    /// let result = diesel::select(jsonb_strip_nulls::<Jsonb, _>(json!({"hello": null})))
    ///     .get_result::<Value>(connection)?;
    /// let expected: Value = json!({});
    /// assert_eq!(result, expected);
    ///

Review comment (refactor):
We need to restrict the generic type `E` here to be either `Json` or `Nullable<Json>`. Also as we return the same output type as input type we don't need the MaybeNullableValue<Json> helper type. You likely need to define a new `JsonOrNullableJson` trait analog to the `JsonbOrNullableJsonb` trait for that.

```suggestion
    fn json_strip_nulls<E: JsonOrNullableJson>(json: E) -> E;
```

Code after:
    /// # }
    /// ```
    fn json_object<Arr: TextArrayOrNullableTextArray + MaybeNullableValue<Json>>(
        text_array: Arr,
    ) -> Arr::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);
    ///
    /// let result = diesel::select(json_typeof::<Json, _>(json!(true)))
    ///     .get_result::<String>(connection)?;
    ///
    /// assert_eq!("boolean".to_string(), result);