You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by mg...@apache.org on 2022/03/22 08:04:48 UTC
[avro] branch branch-1.11 updated: AVRO-3452: Implement custom deserialization for Name that employs the special parsing of name and namespace (#1615)
This is an automated email from the ASF dual-hosted git repository.
mgrigorov pushed a commit to branch branch-1.11
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/branch-1.11 by this push:
new a9a422f AVRO-3452: Implement custom deserialization for Name that employs the special parsing of name and namespace (#1615)
a9a422f is described below
commit a9a422fd7b970c510aa55ee732b42110df24f4d2
Author: Martin Grigorov <ma...@users.noreply.github.com>
AuthorDate: Tue Mar 22 10:04:07 2022 +0200
AVRO-3452: Implement custom deserialization for Name that employs the special parsing of name and namespace (#1615)
* AVRO-3452: Implement custom deserialization for Name that employs the special parsing of name and namespace
Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
* AVRO-3452: Move the use/import of serde::de::Error in a higher scope so that it could be used for .map_err() call too
Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
(cherry picked from commit 8d0e53c3781e4fcfaac61e0bfd9c04b00115ad79)
---
lang/rust/avro/src/schema.rs | 23 +++++++++++++++++++--
lang/rust/avro/tests/schema.rs | 47 +++++++++++++++++++++++++++++++++++-------
2 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index 9c0750b..ed98118 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -228,7 +228,7 @@ impl From<&types::Value> for SchemaKind {
///
/// More information about schema names can be found in the
/// [Avro specification](https://avro.apache.org/docs/current/spec.html#names)
-#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Name {
pub name: String,
pub namespace: Namespace,
@@ -265,7 +265,7 @@ impl Name {
}
/// Parse a `serde_json::Value` into a `Name`.
- fn parse(complex: &Map<String, Value>) -> AvroResult<Self> {
+ pub(crate) fn parse(complex: &Map<String, Value>) -> AvroResult<Self> {
let (name, namespace_from_name) = complex
.name()
.map(|name| Name::get_name_and_namespace(name.as_str()).unwrap())
@@ -335,6 +335,25 @@ impl fmt::Display for Name {
}
}
+impl<'de> Deserialize<'de> for Name {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::de::Deserializer<'de>,
+ {
+ serde_json::Value::deserialize(deserializer).and_then(|value| {
+ use serde::de::Error;
+ if let Value::Object(json) = value {
+ Name::parse(&json).map_err(D::Error::custom)
+ } else {
+ Err(D::Error::custom(format!(
+ "Expected a json object: {:?}",
+ value
+ )))
+ }
+ })
+ }
+}
+
pub(crate) struct ResolvedSchema<'s> {
names_ref: NamesRef<'s>,
root_schema: &'s Schema,
diff --git a/lang/rust/avro/tests/schema.rs b/lang/rust/avro/tests/schema.rs
index c404452..292d0aa 100644
--- a/lang/rust/avro/tests/schema.rs
+++ b/lang/rust/avro/tests/schema.rs
@@ -1077,9 +1077,9 @@ fn test_fullname_name_and_namespace_specified() {
#[test]
fn test_fullname_fullname_and_namespace_specified() {
init();
- let name: Name =
- serde_json::from_str(r#"{"name": "a.b.c.d", "namespace": "o.a.h", "aliases": null}"#)
- .unwrap();
+ let name: Name = serde_json::from_str(r#"{"name": "a.b.c.d", "namespace": "o.a.h"}"#).unwrap();
+ assert_eq!(&name.name, "d");
+ assert_eq!(name.namespace, Some("a.b.c".to_owned()));
let fullname = name.fullname(None);
assert_eq!("a.b.c.d", fullname);
}
@@ -1087,8 +1087,9 @@ fn test_fullname_fullname_and_namespace_specified() {
#[test]
fn test_fullname_name_and_default_namespace_specified() {
init();
- let name: Name =
- serde_json::from_str(r#"{"name": "a", "namespace": null, "aliases": null}"#).unwrap();
+ let name: Name = serde_json::from_str(r#"{"name": "a", "namespace": null}"#).unwrap();
+ assert_eq!(&name.name, "a");
+ assert_eq!(name.namespace, None);
let fullname = name.fullname(Some("b.c.d".into()));
assert_eq!("b.c.d.a", fullname);
}
@@ -1096,18 +1097,48 @@ fn test_fullname_name_and_default_namespace_specified() {
#[test]
fn test_fullname_fullname_and_default_namespace_specified() {
init();
- let name: Name =
- serde_json::from_str(r#"{"name": "a.b.c.d", "namespace": null, "aliases": null}"#).unwrap();
+ let name: Name = serde_json::from_str(r#"{"name": "a.b.c.d", "namespace": null}"#).unwrap();
+ assert_eq!(&name.name, "d");
+ assert_eq!(name.namespace, Some("a.b.c".to_owned()));
let fullname = name.fullname(Some("o.a.h".into()));
assert_eq!("a.b.c.d", fullname);
}
#[test]
+fn test_avro_3452_parsing_name_without_namespace() {
+ init();
+ let name: Name = serde_json::from_str(r#"{"name": "a.b.c.d"}"#).unwrap();
+ assert_eq!(&name.name, "d");
+ assert_eq!(name.namespace, Some("a.b.c".to_owned()));
+ let fullname = name.fullname(None);
+ assert_eq!("a.b.c.d", fullname);
+}
+
+#[test]
+fn test_avro_3452_parsing_name_with_leading_dot_without_namespace() {
+ init();
+ let name: Name = serde_json::from_str(r#"{"name": ".a"}"#).unwrap();
+ assert_eq!(&name.name, "a");
+ assert_eq!(name.namespace, None);
+ assert_eq!("a", name.fullname(None));
+}
+
+#[test]
+fn test_avro_3452_parse_json_without_name_field() {
+ init();
+ let result: serde_json::error::Result<Name> = serde_json::from_str(r#"{"unknown": "a"}"#);
+ assert!(&result.is_err());
+ assert_eq!(result.unwrap_err().to_string(), "No `name` field");
+}
+
+#[test]
fn test_fullname_fullname_namespace_and_default_namespace_specified() {
init();
let name: Name =
serde_json::from_str(r#"{"name": "a.b.c.d", "namespace": "o.a.a", "aliases": null}"#)
.unwrap();
+ assert_eq!(&name.name, "d");
+ assert_eq!(name.namespace, Some("a.b.c".to_owned()));
let fullname = name.fullname(Some("o.a.h".into()));
assert_eq!("a.b.c.d", fullname);
}
@@ -1117,6 +1148,8 @@ fn test_fullname_name_namespace_and_default_namespace_specified() {
init();
let name: Name =
serde_json::from_str(r#"{"name": "a", "namespace": "o.a.a", "aliases": null}"#).unwrap();
+ assert_eq!(&name.name, "a");
+ assert_eq!(name.namespace, Some("o.a.a".to_owned()));
let fullname = name.fullname(Some("o.a.h".into()));
assert_eq!("o.a.a.a", fullname);
}