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
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use crate::datatype::{DataType, Lang};
use crate::individual::Individual;
use serde_json::value::Value as JSONValue;
use serde_json::Map;

pub fn parse_json_to_individual(src: &JSONValue, dest: &mut Individual) -> bool {
    let mut res = true;

    if let Some(props) = src.as_object() {
        for (key, value) in props.iter() {
            if key == "@" {
                if let Some(id) = value.as_str() {
                    dest.set_id(id);
                } else {
                    error!("json->individual: fail get id");
                    res = false;
                }
            } else if let Some(values) = value.as_array() {
                if !json_to_predicate(key, values, dest) {
                    res = false;
                }
            } else {
                error!("json->individual: predicate [{}] must contain an array of values", key);
                res = false;
            }
        }
    }

    res
}

fn get_datatype_from_json(val: Option<&JSONValue>) -> Result<DataType, String> {
    if val.is_none() {
        return Err("not content field type".to_owned());
    }

    let tp = val.unwrap();
    if tp.is_string() {
        if let Some(v) = tp.as_str() {
            if let Some(d) = DataType::new_from_str(v) {
                return Ok(d);
            }
        }
    } else if tp.is_u64() {
        if let Some(v) = tp.as_u64() {
            if let Some(d) = DataType::new_from_u64(v) {
                return Ok(d);
            }
        }
    } else {
        return Err("expected string or integer for value of field [type]".to_owned());
    }

    Err("invalid value of field [type]".to_owned())
}

fn add_string(v: &Map<String, JSONValue>, vdata: &JSONValue, predicate: &str, dest: &mut Individual) {
    if let Some(s) = vdata.as_str() {
        let lang = if let Some(v) = v.get("lang") {
            if v.is_string() {
                Lang::new_from_str(v.as_str().unwrap_or_default().to_lowercase().as_str())
            } else if v.is_number() {
                Lang::new_from_i64(v.as_i64().unwrap_or_default())
            } else {
                Lang::NONE
            }
        } else {
            Lang::NONE
        };

        dest.add_string(predicate, s, lang);
    }
}

fn json_to_predicate(predicate: &str, values: &[JSONValue], dest: &mut Individual) -> bool {
    let mut res = true;
    for val in values {
        if let Some(v) = val.as_object() {
            let vdata = v.get("data");
            if vdata.is_none() {
                error!("json->individual: predicate [{}], value must contain [data]", predicate);
                res = false;
                continue;
            }
            let ptype = get_datatype_from_json(v.get("type"));
            if ptype.is_err() {
                error!("json->individual: predicate [{}], invalid value", predicate);
                res = false;
                continue;
            }
            let vdata = vdata.unwrap();

            match ptype.unwrap() {
                DataType::Uri => {
                    if let Some(v) = vdata.as_str() {
                        dest.add_uri(predicate, v);
                    }
                }
                DataType::String => add_string(v, vdata, predicate, dest),

                DataType::Integer => {
                    if let Some(v) = vdata.as_i64() {
                        dest.add_integer(predicate, v);
                    }
                }
                DataType::Datetime => {
                    if vdata.is_number() {
                        if let Some(v) = vdata.as_i64() {
                            dest.add_datetime(predicate, v);
                        }
                    } else if vdata.is_string() {
                        if let Some(v) = vdata.as_str() {
                            dest.add_datetime_from_str(predicate, v);
                        }
                    }
                }
                DataType::Decimal => {
                    if vdata.is_f64() {
                        if let Some(v) = vdata.as_f64() {
                            dest.add_decimal_from_f64(predicate, v);
                        }
                    } else if vdata.is_number() {
                        if let Some(v) = vdata.as_i64() {
                            dest.add_decimal_from_i64(predicate, v);
                        }
                    } else if vdata.is_string() {
                        if let Some(v) = vdata.as_str() {
                            dest.add_decimal_from_str(predicate, v);
                        }
                    }
                }
                DataType::Boolean => {
                    if let Some(v) = vdata.as_bool() {
                        dest.add_bool(predicate, v);
                    }
                }
                DataType::Binary => {
                    if let Some(v) = vdata.as_str() {
                        dest.add_binary(predicate, v.as_bytes().to_vec());
                    }
                }
            }
        } else {
            error!("json->individual: value for predicate [{}] must contain map", predicate);
            res = false;
        }
    }

    res
}