3
3
use crate :: error:: AvrowErr ;
4
4
use crate :: schema;
5
5
use crate :: schema:: common:: validate_name;
6
+ use crate :: schema:: parser:: parse_default;
6
7
use crate :: schema:: Registry ;
7
8
use crate :: util:: { encode_long, encode_raw_bytes} ;
8
9
use crate :: Schema ;
@@ -37,7 +38,9 @@ impl FieldValue {
37
38
}
38
39
39
40
#[ derive( Debug , Clone , PartialEq , Serialize ) ]
40
- /// The [record](https://avro.apache.org/docs/current/spec.html#schema_record) avro type
41
+ /// The [Record](https://avro.apache.org/docs/current/spec.html#schema_record) avro type.
42
+ /// Avro records translates to a struct in Rust. Any struct that implements serde's
43
+ /// Serializable trait can be converted to an avro record.
41
44
pub struct Record {
42
45
pub ( crate ) name : String ,
43
46
pub ( crate ) fields : IndexMap < String , FieldValue > ,
@@ -60,7 +63,7 @@ impl Record {
60
63
Ok ( ( ) )
61
64
}
62
65
63
- /// Sets the ordering of the field.
66
+ /// Sets the ordering of the field in the record .
64
67
pub fn set_field_order ( & mut self , field_name : & str , order : Order ) -> Result < ( ) , AvrowErr > {
65
68
let a = self
66
69
. fields
@@ -71,7 +74,7 @@ impl Record {
71
74
}
72
75
73
76
/// Creates a record from a [BTreeMap](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html) by consuming it.
74
- /// The values in BTreeMap must implement Into<Value>. The name provided must match with the name in the record
77
+ /// The values in ` BTreeMap` must implement ` Into<Value>` . The ` name` provided must match with the name in the record
75
78
/// schema being provided to the writer.
76
79
pub fn from_btree < K : Into < String > + Ord + Display , V : Into < Value > > (
77
80
name : & str ,
@@ -89,20 +92,37 @@ impl Record {
89
92
Ok ( record)
90
93
}
91
94
92
- /// Creates a record from a json object. A confirming record schema must be provided.
95
+ /// Creates a record from a JSON object (serde_json::Value) . A confirming record schema must be provided.
93
96
pub fn from_json (
94
97
json : serde_json:: Map < String , serde_json:: Value > ,
95
98
schema : & Schema ,
96
99
) -> Result < Value , AvrowErr > {
97
- // let variant = schema.variant;
98
- if let Variant :: Record { name, fields, .. } = & schema. variant {
99
- let mut values = IndexMap :: new ( ) ;
100
- for ( k, v) in json {
101
- let parsed_value = crate :: schema:: parser:: parse_default (
102
- & v,
103
- & fields. get ( & k) . ok_or ( AvrowErr :: DefaultValueParse ) ?. ty ,
104
- ) ?;
105
- values. insert ( k. to_string ( ) , FieldValue :: new ( parsed_value) ) ;
100
+ if let Variant :: Record {
101
+ name,
102
+ fields : record_schema_fields,
103
+ ..
104
+ } = & schema. variant
105
+ {
106
+ let mut values = IndexMap :: with_capacity ( record_schema_fields. len ( ) ) ;
107
+ ' fields: for ( k, v) in record_schema_fields {
108
+ if let Some ( default_value) = json. get ( k) {
109
+ if let Variant :: Union { variants } = & v. ty {
110
+ for var in variants {
111
+ if let Ok ( v) = parse_default ( & default_value, & var) {
112
+ values. insert ( k. to_string ( ) , FieldValue :: new ( v) ) ;
113
+ continue ' fields;
114
+ }
115
+ }
116
+ return Err ( AvrowErr :: FailedDefaultUnion ) ;
117
+ } else {
118
+ let parsed_value = parse_default ( & default_value, & v. ty ) ?;
119
+ values. insert ( k. to_string ( ) , FieldValue :: new ( parsed_value) ) ;
120
+ }
121
+ } else if let Some ( v) = & v. default {
122
+ values. insert ( k. to_string ( ) , FieldValue :: new ( v. clone ( ) ) ) ;
123
+ } else {
124
+ return Err ( AvrowErr :: FieldNotFound ) ;
125
+ }
106
126
}
107
127
108
128
Ok ( Value :: Record ( crate :: value:: Record {
@@ -633,6 +653,7 @@ mod tests {
633
653
use super :: Record ;
634
654
use crate :: from_value;
635
655
use crate :: Schema ;
656
+ use crate :: Value ;
636
657
use serde:: { Deserialize , Serialize } ;
637
658
use std:: collections:: BTreeMap ;
638
659
use std:: str:: FromStr ;
@@ -743,11 +764,34 @@ mod tests {
743
764
let rec = super :: Record :: from_json ( json, & schema) . unwrap ( ) ;
744
765
let mut writer = crate :: Writer :: new ( & schema, vec ! [ ] ) . unwrap ( ) ;
745
766
writer. write ( rec) . unwrap ( ) ;
746
- // writer.flush().unwrap();
747
767
let avro_data = writer. into_inner ( ) . unwrap ( ) ;
748
768
let reader = crate :: Reader :: new ( avro_data. as_slice ( ) ) . unwrap ( ) ;
749
769
for value in reader {
750
770
let _mentors: RustMentors = from_value ( & value) . unwrap ( ) ;
751
771
}
752
772
}
773
+
774
+ #[ test]
775
+ fn record_has_fields_with_default ( ) {
776
+ let schema_str = r##"
777
+ {
778
+ "namespace": "sensor.data",
779
+ "type": "record",
780
+ "name": "common",
781
+ "fields" : [
782
+ {"name": "data", "type": ["null", "string"], "default": null}
783
+ ]
784
+ }
785
+ "## ;
786
+
787
+ let sample_data = r#"{
788
+ "data": null
789
+ }"# ;
790
+
791
+ let serde_json = serde_json:: from_str ( sample_data) . unwrap ( ) ;
792
+ let schema = Schema :: from_str ( schema_str) . unwrap ( ) ;
793
+ let rec = Record :: from_json ( serde_json, & schema) . unwrap ( ) ;
794
+ let field = & rec. as_record ( ) . unwrap ( ) . fields [ "data" ] ;
795
+ assert_eq ! ( field. value, Value :: Null ) ;
796
+ }
753
797
}
0 commit comments