• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

getdozer / dozer / 5640896332

pending completion
5640896332

push

github

web-flow
chore: Remove `Schema::identifier` (#1776)

1574 of 1574 new or added lines in 102 files covered. (100.0%)

42145 of 54025 relevant lines covered (78.01%)

17469.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.02
/dozer-types/src/json_types.rs
1
use crate::errors::types::DeserializationError;
2
use crate::types::{DozerDuration, Field, DATE_FORMAT};
3
use chrono::SecondsFormat;
4
use ordered_float::OrderedFloat;
5
use prost_types::value::Kind;
6
use prost_types::{ListValue, Struct, Value as ProstValue};
7
use rust_decimal::prelude::FromPrimitive;
8
use serde::{Deserialize, Serialize};
9
use serde_json::{json as serde_json, Map, Value};
10
use std::borrow::Cow;
11
use std::collections::BTreeMap;
12
use std::fmt::{Display, Formatter};
13
use std::str::FromStr;
14

15
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash)]
147,776✔
16
pub enum JsonValue {
17
    Null,
18
    Bool(bool),
19
    Number(OrderedFloat<f64>),
20
    String(String),
21
    Array(Vec<JsonValue>),
22
    Object(BTreeMap<String, JsonValue>),
23
}
24

25
#[allow(clippy::derivable_impls)]
26
impl Default for JsonValue {
27
    fn default() -> JsonValue {
×
28
        JsonValue::Null
×
29
    }
×
30
}
31

32
impl JsonValue {
33
    pub fn as_array(&self) -> Option<&Vec<JsonValue>> {
156✔
34
        match self {
156✔
35
            JsonValue::Array(array) => Some(array),
156✔
36
            _ => None,
×
37
        }
38
    }
156✔
39

40
    pub fn as_object(&self) -> Option<&BTreeMap<String, JsonValue>> {
×
41
        match self {
×
42
            JsonValue::Object(map) => Some(map),
×
43
            _ => None,
×
44
        }
45
    }
×
46

47
    pub fn as_str(&self) -> Option<&str> {
2✔
48
        match self {
2✔
49
            JsonValue::String(s) => Some(s),
×
50
            _ => None,
2✔
51
        }
52
    }
2✔
53

54
    pub fn as_i64(&self) -> Option<i64> {
1✔
55
        match self {
1✔
56
            JsonValue::Number(n) => Some(n.0 as i64),
×
57
            _ => None,
1✔
58
        }
59
    }
1✔
60

61
    pub fn as_i128(&self) -> Option<i128> {
1✔
62
        match self {
1✔
63
            JsonValue::Number(n) => i128::from_f64(n.0),
×
64
            _ => None,
1✔
65
        }
66
    }
1✔
67

68
    pub fn as_u64(&self) -> Option<u64> {
156✔
69
        match self {
156✔
70
            JsonValue::Number(n) => Some(n.0 as u64),
156✔
71
            _ => None,
×
72
        }
73
    }
156✔
74

75
    pub fn as_u128(&self) -> Option<u128> {
1✔
76
        match self {
1✔
77
            JsonValue::Number(n) => u128::from_f64(n.0),
×
78
            _ => None,
1✔
79
        }
80
    }
1✔
81

82
    pub fn as_f64(&self) -> Option<f64> {
1✔
83
        match self {
1✔
84
            JsonValue::Number(n) => Some(n.0),
×
85
            _ => None,
1✔
86
        }
87
    }
1✔
88

89
    pub fn as_bool(&self) -> Option<bool> {
1✔
90
        match *self {
1✔
91
            JsonValue::Bool(b) => Some(b),
×
92
            _ => None,
1✔
93
        }
94
    }
1✔
95

96
    pub fn as_null(&self) -> Option<()> {
1✔
97
        match *self {
1✔
98
            JsonValue::Null => Some(()),
×
99
            _ => None,
1✔
100
        }
101
    }
1✔
102
}
103

104
impl Display for JsonValue {
105
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29✔
106
        match self {
29✔
107
            JsonValue::Null => f.write_str("NULL"),
×
108
            JsonValue::Bool(v) => f.write_str(&format!("{v}")),
×
109
            JsonValue::Number(v) => f.write_str(&format!("{v}")),
25✔
110
            JsonValue::String(v) => f.write_str(&v.to_string()),
×
111
            JsonValue::Array(v) => {
4✔
112
                let list: Vec<String> = v.iter().map(|val| format!("{val}")).collect();
12✔
113
                let data = &format!("[{}]", list.join(","));
4✔
114
                f.write_str(data)
4✔
115
            }
116
            JsonValue::Object(v) => {
×
117
                let list: Vec<String> = v.iter().map(|(key, val)| format!("{key}:{val}")).collect();
×
118
                let data = &format!("{{ {} }}", list.join(","));
×
119
                f.write_str(data)
×
120
            }
121
        }
122
    }
29✔
123
}
124

125
impl FromStr for JsonValue {
126
    type Err = DeserializationError;
127

128
    fn from_str(s: &str) -> Result<Self, Self::Err> {
56✔
129
        let object = serde_json::from_str(s);
56✔
130
        if object.is_ok() {
56✔
131
            serde_json_to_json_value(object?)
16✔
132
        } else {
133
            let f = OrderedFloat::from_str(s)
40✔
134
                .map_err(|e| DeserializationError::Custom(Box::from(format!("{:?}", e))));
40✔
135
            if f.is_ok() {
40✔
136
                Ok(JsonValue::Number(f?))
×
137
            } else {
138
                let b = bool::from_str(s)
40✔
139
                    .map_err(|e| DeserializationError::Custom(Box::from(format!("{:?}", e))));
40✔
140
                if b.is_ok() {
40✔
141
                    Ok(JsonValue::Bool(b?))
×
142
                } else {
143
                    Ok(JsonValue::String(String::from(s)))
40✔
144
                }
145
            }
146
        }
147
    }
56✔
148
}
149

150
impl From<usize> for JsonValue {
151
    fn from(f: usize) -> Self {
×
152
        From::from(f as f64)
×
153
    }
×
154
}
155

156
impl From<f32> for JsonValue {
157
    fn from(f: f32) -> Self {
×
158
        From::from(f as f64)
×
159
    }
×
160
}
161

162
impl From<f64> for JsonValue {
163
    fn from(f: f64) -> Self {
78✔
164
        JsonValue::Number(OrderedFloat(f))
78✔
165
    }
78✔
166
}
167

168
impl From<bool> for JsonValue {
169
    fn from(f: bool) -> Self {
×
170
        JsonValue::Bool(f)
×
171
    }
×
172
}
173

174
impl From<String> for JsonValue {
175
    fn from(f: String) -> Self {
×
176
        JsonValue::String(f)
×
177
    }
×
178
}
179

180
impl<'a> From<&'a str> for JsonValue {
181
    fn from(f: &str) -> Self {
×
182
        JsonValue::String(f.to_string())
×
183
    }
×
184
}
185

186
impl<'a> From<Cow<'a, str>> for JsonValue {
187
    fn from(f: Cow<'a, str>) -> Self {
×
188
        JsonValue::String(f.into_owned())
×
189
    }
×
190
}
191

192
impl From<OrderedFloat<f64>> for JsonValue {
193
    fn from(f: OrderedFloat<f64>) -> Self {
×
194
        JsonValue::Number(f)
×
195
    }
×
196
}
197

198
impl From<BTreeMap<String, JsonValue>> for JsonValue {
199
    fn from(f: BTreeMap<String, JsonValue>) -> Self {
×
200
        JsonValue::Object(f)
×
201
    }
×
202
}
203

204
impl<T: Into<JsonValue>> From<Vec<T>> for JsonValue {
205
    fn from(f: Vec<T>) -> Self {
×
206
        JsonValue::Array(f.into_iter().map(Into::into).collect())
×
207
    }
×
208
}
209

210
impl<'a, T: Clone + Into<JsonValue>> From<&'a [T]> for JsonValue {
211
    fn from(f: &'a [T]) -> Self {
×
212
        JsonValue::Array(f.iter().cloned().map(Into::into).collect())
×
213
    }
×
214
}
215

216
impl<T: Into<JsonValue>> FromIterator<T> for JsonValue {
217
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
×
218
        JsonValue::Array(iter.into_iter().map(Into::into).collect())
×
219
    }
×
220
}
221

222
impl<K: Into<String>, V: Into<JsonValue>> FromIterator<(K, V)> for JsonValue {
223
    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
×
224
        JsonValue::Object(
×
225
            iter.into_iter()
×
226
                .map(|(k, v)| (k.into(), v.into()))
×
227
                .collect(),
×
228
        )
×
229
    }
×
230
}
231

232
impl From<()> for JsonValue {
233
    fn from((): ()) -> Self {
×
234
        JsonValue::Null
×
235
    }
×
236
}
237

238
impl<T> From<Option<T>> for JsonValue
239
where
240
    T: Into<JsonValue>,
241
{
242
    fn from(opt: Option<T>) -> Self {
×
243
        match opt {
×
244
            None => JsonValue::Null,
×
245
            Some(value) => Into::into(value),
×
246
        }
247
    }
×
248
}
249

250
fn convert_x_y_to_object((x, y): &(OrderedFloat<f64>, OrderedFloat<f64>)) -> Value {
1✔
251
    let mut m = Map::new();
1✔
252
    m.insert("x".to_string(), Value::from(x.0));
1✔
253
    m.insert("y".to_string(), Value::from(y.0));
1✔
254
    Value::Object(m)
1✔
255
}
1✔
256

257
fn convert_duration_to_object(d: &DozerDuration) -> Value {
1✔
258
    let mut m = Map::new();
1✔
259
    m.insert("value".to_string(), Value::from(d.0.as_nanos().to_string()));
1✔
260
    m.insert("time_unit".to_string(), Value::from(d.1.to_string()));
1✔
261
    Value::Object(m)
1✔
262
}
1✔
263

264
/// Should be consistent with `convert_cache_type_to_schema_type`.
265
pub fn field_to_json_value(field: Field) -> Result<Value, DeserializationError> {
20,358✔
266
    match field {
20,358✔
267
        Field::UInt(n) => Ok(Value::from(n)),
8,139✔
268
        Field::U128(n) => Ok(Value::String(n.to_string())),
×
269
        Field::Int(n) => Ok(Value::from(n)),
1✔
270
        Field::I128(n) => Ok(Value::String(n.to_string())),
×
271
        Field::Float(n) => Ok(Value::from(n.0)),
1✔
272
        Field::Boolean(b) => Ok(Value::from(b)),
1✔
273
        Field::String(s) => Ok(Value::from(s)),
4,070✔
274
        Field::Text(n) => Ok(Value::from(n)),
1✔
275
        Field::Binary(b) => Ok(Value::from(b)),
1✔
276
        Field::Decimal(n) => Ok(Value::String(n.to_string())),
1✔
277
        Field::Timestamp(ts) => Ok(Value::String(
1✔
278
            ts.to_rfc3339_opts(SecondsFormat::Millis, true),
1✔
279
        )),
1✔
280
        Field::Date(n) => Ok(Value::String(n.format(DATE_FORMAT).to_string())),
1✔
281
        Field::Json(b) => json_value_to_serde_json(b),
1✔
282
        Field::Point(point) => Ok(convert_x_y_to_object(&point.0.x_y())),
1✔
283
        Field::Duration(d) => Ok(convert_duration_to_object(&d)),
1✔
284
        Field::Null => Ok(Value::Null),
8,138✔
285
    }
286
}
20,358✔
287

288
pub fn json_value_to_serde_json(value: JsonValue) -> Result<Value, DeserializationError> {
13✔
289
    match value {
13✔
290
        JsonValue::Null => Ok(Value::Null),
×
291
        JsonValue::Bool(b) => Ok(Value::Bool(b)),
×
292
        JsonValue::Number(n) => {
12✔
293
            if n.0.is_finite() {
12✔
294
                Ok(serde_json!(n.0))
12✔
295
            } else {
296
                Err(DeserializationError::F64TypeConversionError)
×
297
            }
298
        }
299
        JsonValue::String(s) => Ok(Value::String(s)),
×
300
        JsonValue::Array(a) => {
1✔
301
            let mut lst: Vec<Value> = vec![];
1✔
302
            for val in a {
13✔
303
                lst.push(json_value_to_serde_json(val)?);
12✔
304
            }
305
            Ok(Value::Array(lst))
1✔
306
        }
307
        JsonValue::Object(o) => {
×
308
            let mut values: Map<String, Value> = Map::new();
×
309
            for (key, val) in o {
×
310
                values.insert(key, json_value_to_serde_json(val)?);
×
311
            }
312
            Ok(Value::Object(values))
×
313
        }
314
    }
315
}
13✔
316

317
pub fn prost_to_json_value(val: ProstValue) -> JsonValue {
×
318
    match val.kind {
×
319
        Some(v) => match v {
×
320
            Kind::NullValue(_) => JsonValue::Null,
×
321
            Kind::BoolValue(b) => JsonValue::Bool(b),
×
322
            Kind::NumberValue(n) => JsonValue::Number(OrderedFloat(n)),
×
323
            Kind::StringValue(s) => JsonValue::String(s),
×
324
            Kind::ListValue(l) => {
×
325
                JsonValue::Array(l.values.into_iter().map(prost_to_json_value).collect())
×
326
            }
327
            Kind::StructValue(s) => JsonValue::Object(
×
328
                s.fields
×
329
                    .into_iter()
×
330
                    .map(|(key, val)| (key, prost_to_json_value(val)))
×
331
                    .collect(),
×
332
            ),
×
333
        },
334
        None => JsonValue::Null,
×
335
    }
336
}
×
337

338
pub fn json_value_to_prost(val: JsonValue) -> ProstValue {
×
339
    ProstValue {
×
340
        kind: match val {
×
341
            JsonValue::Null => Some(Kind::NullValue(0)),
×
342
            JsonValue::Bool(b) => Some(Kind::BoolValue(b)),
×
343
            JsonValue::Number(n) => Some(Kind::NumberValue(*n)),
×
344
            JsonValue::String(s) => Some(Kind::StringValue(s)),
×
345
            JsonValue::Array(a) => {
×
346
                let values: prost::alloc::vec::Vec<ProstValue> =
×
347
                    a.into_iter().map(json_value_to_prost).collect();
×
348
                Some(Kind::ListValue(ListValue { values }))
×
349
            }
350
            JsonValue::Object(o) => {
×
351
                let fields: prost::alloc::collections::BTreeMap<
×
352
                    prost::alloc::string::String,
×
353
                    ProstValue,
×
354
                > = o
×
355
                    .into_iter()
×
356
                    .map(|(key, val)| (key, json_value_to_prost(val)))
×
357
                    .collect();
×
358
                Some(Kind::StructValue(Struct { fields }))
×
359
            }
360
        },
361
    }
362
}
×
363

364
pub fn serde_json_to_json_value(value: Value) -> Result<JsonValue, DeserializationError> {
1,875✔
365
    match value {
1,875✔
366
        Value::Null => Ok(JsonValue::Null),
×
367
        Value::Bool(b) => Ok(JsonValue::Bool(b)),
13✔
368
        Value::Number(n) => Ok(JsonValue::Number(OrderedFloat(match n.as_f64() {
388✔
369
            Some(f) => f,
388✔
370
            None => return Err(DeserializationError::F64TypeConversionError),
×
371
        }))),
372
        Value::String(s) => Ok(JsonValue::String(s)),
729✔
373
        Value::Array(a) => {
185✔
374
            let mut lst = vec![];
185✔
375
            for val in a {
625✔
376
                lst.push(serde_json_to_json_value(val)?);
440✔
377
            }
378
            Ok(JsonValue::Array(lst))
185✔
379
        }
380
        Value::Object(o) => {
560✔
381
            let mut values: BTreeMap<String, JsonValue> = BTreeMap::<String, JsonValue>::new();
560✔
382
            for (key, val) in o {
1,653✔
383
                values.insert(key, serde_json_to_json_value(val)?);
1,093✔
384
            }
385
            Ok(JsonValue::Object(values))
560✔
386
        }
387
    }
388
}
1,875✔
389

390
#[cfg(test)]
391
mod tests {
392
    use crate::{
393
        chrono::{NaiveDate, Offset, TimeZone, Utc},
394
        json_value_to_field,
395
        ordered_float::OrderedFloat,
396
        rust_decimal::Decimal,
397
        types::{DozerPoint, Field, FieldType, TimeUnit},
398
    };
399

400
    use std::time::Duration;
401

402
    use super::*;
403

404
    fn test_field_conversion(field_type: FieldType, field: Field) {
13✔
405
        // Convert the field to a JSON value.
13✔
406
        let value = field_to_json_value(field.clone());
13✔
407

13✔
408
        // Convert the JSON value back to a Field.
13✔
409
        let deserialized = json_value_to_field(value.unwrap(), field_type, true).unwrap();
13✔
410

13✔
411
        assert_eq!(deserialized, field, "must be equal");
13✔
412
    }
13✔
413

414
    #[test]
1✔
415
    fn test_field_types_json_conversion() {
1✔
416
        let fields = vec![
1✔
417
            (FieldType::Int, Field::Int(-1)),
1✔
418
            (FieldType::UInt, Field::UInt(1)),
1✔
419
            (FieldType::Float, Field::Float(OrderedFloat(1.1))),
1✔
420
            (FieldType::Boolean, Field::Boolean(true)),
1✔
421
            (FieldType::String, Field::String("a".to_string())),
1✔
422
            (FieldType::Binary, Field::Binary(b"asdf".to_vec())),
1✔
423
            (FieldType::Decimal, Field::Decimal(Decimal::new(202, 2))),
1✔
424
            (
1✔
425
                FieldType::Timestamp,
1✔
426
                Field::Timestamp(Utc.fix().with_ymd_and_hms(2001, 1, 1, 0, 4, 0).unwrap()),
1✔
427
            ),
1✔
428
            (
1✔
429
                FieldType::Date,
1✔
430
                Field::Date(NaiveDate::from_ymd_opt(2022, 11, 24).unwrap()),
1✔
431
            ),
1✔
432
            (
1✔
433
                FieldType::Json,
1✔
434
                Field::Json(JsonValue::Array(vec![
1✔
435
                    JsonValue::Number(OrderedFloat(123_f64)),
1✔
436
                    JsonValue::Number(OrderedFloat(34_f64)),
1✔
437
                    JsonValue::Number(OrderedFloat(97_f64)),
1✔
438
                    JsonValue::Number(OrderedFloat(98_f64)),
1✔
439
                    JsonValue::Number(OrderedFloat(99_f64)),
1✔
440
                    JsonValue::Number(OrderedFloat(34_f64)),
1✔
441
                    JsonValue::Number(OrderedFloat(58_f64)),
1✔
442
                    JsonValue::Number(OrderedFloat(34_f64)),
1✔
443
                    JsonValue::Number(OrderedFloat(102_f64)),
1✔
444
                    JsonValue::Number(OrderedFloat(111_f64)),
1✔
445
                    JsonValue::Number(OrderedFloat(111_f64)),
1✔
446
                    JsonValue::Number(OrderedFloat(34_f64)),
1✔
447
                ])),
1✔
448
            ),
1✔
449
            (FieldType::Text, Field::Text("lorem ipsum".to_string())),
1✔
450
            (
1✔
451
                FieldType::Point,
1✔
452
                Field::Point(DozerPoint::from((3.234, 4.567))),
1✔
453
            ),
1✔
454
            (
1✔
455
                FieldType::Duration,
1✔
456
                Field::Duration(DozerDuration(
1✔
457
                    Duration::from_nanos(123_u64),
1✔
458
                    TimeUnit::Nanoseconds,
1✔
459
                )),
1✔
460
            ),
1✔
461
        ];
1✔
462
        for (field_type, field) in fields {
14✔
463
            test_field_conversion(field_type, field);
13✔
464
        }
13✔
465
    }
1✔
466
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc