rs_avro_schema_gen/record/
flat.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::io;

use serde_json::Map;
use serde_json::Value;

#[derive(serde::Serialize)]
pub struct FlatField {
    pub name: String,
    pub r#type: String,
}

#[derive(serde::Serialize)]
pub struct FlatRecord {
    pub name: String,
    pub r#type: String,
    pub namespace: Option<String>,
    pub fields: Vec<FlatField>,
}

pub fn json_sample_data2schema(
    name: String,
    namespace: Option<String>,
    j: Value,
) -> Result<FlatRecord, io::Error> {
    let m: Map<String, Value> = match j {
        Value::Object(o) => Ok(o),
        _ => Err(io::Error::other(format!("invalid input json: {j}"))),
    }?;
    let pairs = m.into_iter();
    let rfields = pairs.map(|pair| {
        let (key, val) = pair;
        let typname: Result<&str, io::Error> = match val {
            Value::Null => Err(io::Error::other("null value got")),
            Value::Bool(_) => Ok("boolean"),
            Value::Number(n) => match n.is_f64() {
                true => Ok("double"),
                false => Ok("long"),
            },
            Value::String(_) => Ok("string"),
            Value::Array(_) => Err(io::Error::other("array got")),
            Value::Object(_) => Err(io::Error::other("object got")),
        };
        typname.map(|name: &str| FlatField {
            name: key,
            r#type: name.into(),
        })
    });
    let collected: Result<Vec<_>, _> = rfields.collect();
    let fields: Vec<FlatField> = collected?;
    Ok(FlatRecord {
        name,
        r#type: "record".into(),
        namespace,
        fields,
    })
}

pub fn json_sample_string2schema(
    name: String,
    namespace: Option<String>,
    jstr: String,
) -> Result<FlatRecord, io::Error> {
    let val: Value = serde_json::from_str(jstr.as_str()).map_err(io::Error::other)?;
    json_sample_data2schema(name, namespace, val)
}

pub fn json_sample_bytes2schema(
    name: String,
    namespace: Option<String>,
    jbytes: Vec<u8>,
) -> Result<FlatRecord, io::Error> {
    let val: Value = serde_json::from_slice(&jbytes).map_err(io::Error::other)?;
    json_sample_data2schema(name, namespace, val)
}