Skip to content

Commit

Permalink
AVRO-3928: [Rust] Convert serde_json::Value::Number to apache_avro::t…
Browse files Browse the repository at this point in the history
…ypes::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]>
  • Loading branch information
martin-g authored Jan 11, 2024
1 parent c1d5b97 commit b9d8a6b
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
30 changes: 30 additions & 0 deletions lang/rust/avro/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
}
55 changes: 54 additions & 1 deletion lang/rust/avro/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -1154,6 +1161,7 @@ mod tests {
};
use num_bigint::BigInt;
use pretty_assertions::assert_eq;
use serde_json::json;
use uuid::Uuid;

#[test]
Expand Down Expand Up @@ -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()
)
);
}
}

0 comments on commit b9d8a6b

Please sign in to comment.