This is an automated email from the ASF dual-hosted git repository.
mgrigorov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/main by this push:
new b9d8a6ba7 AVRO-3928: [Rust] Convert serde_json::Value::Number to
apache_avro::types::Value::Int when possible (#2682)
b9d8a6ba7 is described below
commit b9d8a6ba7b3a1e4c1a9d4fa0ce0cc10fcfe4a9b8
Author: Martin Grigorov <[email protected]>
AuthorDate: Thu Jan 11 14:49:30 2024 +0200
AVRO-3928: [Rust] Convert serde_json::Value::Number to
apache_avro::types::Value::Int when possible (#2682)
* AVRO-3928: [Rust] Convert serde_json::Value::Number to
apache_avro::types::Value::Int when possible
If the number is bigger than i32::MIN and smaller than i32::MAX then
convert to types::Value::Int, otherwise to types::Value::Long
Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
* AVRO-3928: [Rust] Add more unit tests for
types::Value::from(serde_json::Value)
Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
---------
Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
---
lang/rust/avro/src/schema.rs | 30 ++++++++++++++++++++++++
lang/rust/avro/src/types.rs | 55 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index 680a54a02..a7c622335 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -6611,4 +6611,34 @@ mod tests {
Ok(())
}
+
+ #[test]
+ fn avro_3928_parse_int_based_schema_with_default() -> TestResult {
+ let schema = r#"
+ {
+ "type": "record",
+ "name": "DateLogicalType",
+ "fields": [ {
+ "name": "birthday",
+ "type": {"type": "int", "logicalType": "date"},
+ "default": 1681601653
+ } ]
+ }"#;
+
+ match Schema::parse_str(schema)? {
+ Schema::Record(record_schema) => {
+ assert_eq!(record_schema.fields.len(), 1);
+ let field = record_schema.fields.first().unwrap();
+ assert_eq!(field.name, "birthday");
+ assert_eq!(field.schema, Schema::Date);
+ assert_eq!(
+ types::Value::from(field.default.clone().unwrap()),
+ types::Value::Int(1681601653)
+ );
+ }
+ _ => unreachable!("Expected Schema::Record"),
+ }
+
+ Ok(())
+ }
}
diff --git a/lang/rust/avro/src/types.rs b/lang/rust/avro/src/types.rs
index 62752bbba..97b99a81a 100644
--- a/lang/rust/avro/src/types.rs
+++ b/lang/rust/avro/src/types.rs
@@ -281,7 +281,14 @@ impl From<JsonValue> for Value {
match value {
JsonValue::Null => Self::Null,
JsonValue::Bool(b) => b.into(),
- JsonValue::Number(ref n) if n.is_i64() =>
Value::Long(n.as_i64().unwrap()),
+ JsonValue::Number(ref n) if n.is_i64() => {
+ let n = n.as_i64().unwrap();
+ if n >= i32::MIN as i64 && n <= i32::MAX as i64 {
+ Value::Int(n as i32)
+ } else {
+ Value::Long(n)
+ }
+ }
JsonValue::Number(ref n) if n.is_f64() =>
Value::Double(n.as_f64().unwrap()),
JsonValue::Number(n) => Value::Long(n.as_u64().unwrap() as i64),
// TODO: Not so great
JsonValue::String(s) => s.into(),
@@ -1154,6 +1161,7 @@ mod tests {
};
use num_bigint::BigInt;
use pretty_assertions::assert_eq;
+ use serde_json::json;
use uuid::Uuid;
#[test]
@@ -3061,4 +3069,49 @@ Field with name '"b"' is not a member of the map items"#,
Ok(())
}
+
+ #[test]
+ fn avro_3928_from_serde_value_to_types_value() {
+ assert_eq!(Value::from(serde_json::Value::Null), Value::Null);
+ assert_eq!(Value::from(json!(true)), Value::Boolean(true));
+ assert_eq!(Value::from(json!(false)), Value::Boolean(false));
+ assert_eq!(Value::from(json!(0)), Value::Int(0));
+ assert_eq!(Value::from(json!(i32::MIN)), Value::Int(i32::MIN));
+ assert_eq!(Value::from(json!(i32::MAX)), Value::Int(i32::MAX));
+ assert_eq!(
+ Value::from(json!(i32::MIN as i64 - 1)),
+ Value::Long(i32::MIN as i64 - 1)
+ );
+ assert_eq!(
+ Value::from(json!(i32::MAX as i64 + 1)),
+ Value::Long(i32::MAX as i64 + 1)
+ );
+ assert_eq!(Value::from(json!(1.23)), Value::Double(1.23));
+ assert_eq!(Value::from(json!(-1.23)), Value::Double(-1.23));
+ assert_eq!(Value::from(json!(u64::MIN)), Value::Int(u64::MIN as i32));
+ assert_eq!(Value::from(json!(u64::MAX)), Value::Long(u64::MAX as i64));
+ assert_eq!(
+ Value::from(json!("some text")),
+ Value::String("some text".into())
+ );
+ assert_eq!(
+ Value::from(json!(["text1", "text2", "text3"])),
+ Value::Array(vec![
+ Value::String("text1".into()),
+ Value::String("text2".into()),
+ Value::String("text3".into())
+ ])
+ );
+ assert_eq!(
+ Value::from(json!({"key1": "value1", "key2": "value2"})),
+ Value::Map(
+ vec![
+ ("key1".into(), Value::String("value1".into())),
+ ("key2".into(), Value::String("value2".into()))
+ ]
+ .into_iter()
+ .collect()
+ )
+ );
+ }
}