Repository: GREsau/schemars (rust)

Issue:
Schema for BigDecimal is not correct
## Problem

`0.8.8` version added schema for `BigDecimal`, but it is incorrect, because BigDecimal serialized as string, and can be deserialized from string, number or integer.

## Details

Current schema
```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Number",
  "type": "number"
}
```

For example:
```rust
use bigdecimal::BigDecimal;
use schemars::schema_for;

fn main() {
    let schema = schema_for!(BigDecimal);
    println!("{}", serde_json::to_string_pretty(&schema).unwrap());
    println!(
        "{:?}",
        serde_json::to_value(&BigDecimal::default()).unwrap()
    )
}
```

gives

```
Schema: {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Number",
  "type": "number"
}
Serialized: String("0")
```

see https://www.jsonschemavalidator.net/s/s2ULf39e as well.

And about deserialization:

```rust
use bigdecimal::BigDecimal;

fn main() {
    assert!(serde_json::from_str::<BigDecimal>("123").is_ok());
    assert!(serde_json::from_str::<BigDecimal>("123.123").is_ok());
    assert!(serde_json::from_str::<BigDecimal>("\"123\"").is_ok());
}
```

## Solution

I don't have any _good_ solutions. The problem is: this type have different schemas for deserialization and serialization. One possible solution: use most common type here - string and then add description and pattern to it.

I recently faced same problem in my work project, and we came up with 2 wrapper types, which have different `JsonSchema` implementations, but this is quite ugly and would not be suitable for this lib I think.


Pull request:
Fix schemas for bigdecimal/rust_decimal
Both of these crates serialise decimals as strings, not as plain numbers.

Half-fixes #123 - there's not yet a good way to handle different schemas for serialization vs deserialization, so this PR just makes the schemas match how these types are serialized (numeric strings).

Patch:
diff --git a/schemars/Cargo.toml b/schemars/Cargo.toml
index 81d1193..3aedb49 100644
--- a/schemars/Cargo.toml
+++ b/schemars/Cargo.toml
@@ -120,5 +120,9 @@ required-features = ["smol_str"]
 name = "semver"
 required-features = ["semver"]
 
+[[test]]
+name = "decimal"
+required-features = ["rust_decimal", "bigdecimal"]
+
 [package.metadata.docs.rs]
 all-features = true
diff --git a/schemars/src/json_schema_impls/decimal.rs b/schemars/src/json_schema_impls/decimal.rs
index d7fc8a1..4f908a2 100644
--- a/schemars/src/json_schema_impls/decimal.rs
+++ b/schemars/src/json_schema_impls/decimal.rs
@@ -4,19 +4,20 @@ use crate::JsonSchema;
 
 macro_rules! decimal_impl {
     ($type:ty) => {
-        decimal_impl!($type => Number, "Number");
-    };
-    ($type:ty => $instance_type:ident, $name:expr) => {
         impl JsonSchema for $type {
             no_ref_schema!();
 
             fn schema_name() -> String {
-                $name.to_owned()
+                "Decimal".to_owned()
             }
 
             fn json_schema(_: &mut SchemaGenerator) -> Schema {
                 SchemaObject {
-                    instance_type: Some(InstanceType::$instance_type.into()),
+                    instance_type: Some(InstanceType::String.into()),
+                    string: Some(Box::new(StringValidation {
+                        pattern: Some(r"^-?[0-9]+(\.[0-9]+)?$".to_owned()),
+                        ..Default::default()
+                    })),
                     ..Default::default()
                 }
                 .into()


Test patch:
diff --git a/schemars/tests/decimal.rs b/schemars/tests/decimal.rs
new file mode 100644
index 0000000..7c3caa1
--- /dev/null
+++ b/schemars/tests/decimal.rs
@@ -0,0 +1,12 @@
+mod util;
+use util::*;
+
+#[test]
+fn rust_decimal() -> TestResult {
+    test_default_generated_schema::<rust_decimal::Decimal>("rust_decimal")
+}
+
+#[test]
+fn bigdecimal() -> TestResult {
+    test_default_generated_schema::<bigdecimal::BigDecimal>("bigdecimal")
+}
diff --git a/schemars/tests/expected/bigdecimal.json b/schemars/tests/expected/bigdecimal.json
new file mode 100644
index 0000000..855db6f
--- /dev/null
+++ b/schemars/tests/expected/bigdecimal.json
@@ -0,0 +1,6 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "title": "Decimal",
+  "type": "string",
+  "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
+}
\ No newline at end of file
diff --git a/schemars/tests/expected/rust_decimal.json b/schemars/tests/expected/rust_decimal.json
new file mode 100644
index 0000000..855db6f
--- /dev/null
+++ b/schemars/tests/expected/rust_decimal.json
@@ -0,0 +1,6 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "title": "Decimal",
+  "type": "string",
+  "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
+}
\ No newline at end of file