|
| 1 | +/* |
| 2 | +gson:Value is roughly a mirror of serde_json::Value |
| 3 | +with added support for the concept of "Absent" so we |
| 4 | +can differentiate between Null literals and values that |
| 5 | +were not provided by the user. |
| 6 | +*/ |
| 7 | +use serde_json; |
| 8 | +use std::collections::HashMap; |
| 9 | + |
| 10 | +#[derive(Clone, Debug, PartialEq)] |
| 11 | +pub enum Value { |
| 12 | + Absent, |
| 13 | + Null, |
| 14 | + Number(Number), |
| 15 | + String(String), |
| 16 | + Boolean(bool), |
| 17 | + Array(Vec<Value>), |
| 18 | + Object(HashMap<String, Value>), |
| 19 | +} |
| 20 | + |
| 21 | +#[derive(Clone, Debug, PartialEq)] |
| 22 | +pub enum Number { |
| 23 | + Integer(i64), |
| 24 | + Float(f64), |
| 25 | +} |
| 26 | + |
| 27 | +pub fn json_to_gson(val: &serde_json::Value) -> Result<Value, String> { |
| 28 | + use serde_json::Value as JsonValue; |
| 29 | + |
| 30 | + let v = match val { |
| 31 | + JsonValue::Null => Value::Null, |
| 32 | + JsonValue::Bool(x) => Value::Boolean(x.to_owned()), |
| 33 | + JsonValue::String(x) => Value::String(x.to_owned()), |
| 34 | + JsonValue::Array(x) => { |
| 35 | + let mut arr = vec![]; |
| 36 | + for jelem in x { |
| 37 | + let gelem = json_to_gson(jelem)?; |
| 38 | + arr.push(gelem); |
| 39 | + } |
| 40 | + Value::Array(arr) |
| 41 | + } |
| 42 | + JsonValue::Number(x) => { |
| 43 | + let val: Option<i64> = x.as_i64(); |
| 44 | + match val { |
| 45 | + Some(num) => { |
| 46 | + let i_val = Number::Integer(num); |
| 47 | + Value::Number(i_val) |
| 48 | + } |
| 49 | + None => { |
| 50 | + let f_val: f64 = x |
| 51 | + .as_f64() |
| 52 | + .ok_or("Failed to handle numeric user input".to_string())?; |
| 53 | + Value::Number(Number::Float(f_val)) |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + JsonValue::Object(kv) => { |
| 58 | + let mut hmap = HashMap::new(); |
| 59 | + for (key, v) in kv.iter() { |
| 60 | + let gson_val = json_to_gson(v)?; |
| 61 | + hmap.insert(key.to_owned(), gson_val); |
| 62 | + } |
| 63 | + Value::Object(hmap) |
| 64 | + } |
| 65 | + }; |
| 66 | + Ok(v) |
| 67 | +} |
| 68 | + |
| 69 | +pub fn gson_to_json(val: &Value) -> Result<serde_json::Value, String> { |
| 70 | + use serde_json::Value as JsonValue; |
| 71 | + |
| 72 | + let v = match val { |
| 73 | + Value::Absent => { |
| 74 | + return Err("Encounterd `Absent` value while transforming between GraphQL intermediate object notation and JSON".to_string()) |
| 75 | + }, |
| 76 | + Value::Null => JsonValue::Null, |
| 77 | + Value::Boolean(x) => JsonValue::Bool(x.to_owned()), |
| 78 | + Value::String(x) => JsonValue::String(x.to_owned()), |
| 79 | + Value::Array(x) => { |
| 80 | + let mut arr = vec![]; |
| 81 | + for gelem in x { |
| 82 | + let jelem = gson_to_json(gelem)?; |
| 83 | + arr.push(jelem); |
| 84 | + } |
| 85 | + JsonValue::Array(arr) |
| 86 | + } |
| 87 | + Value::Number(x) => match x { |
| 88 | + Number::Integer(y) => serde_json::json!(y), |
| 89 | + Number::Float(y) => serde_json::json!(y), |
| 90 | + }, |
| 91 | + Value::Object(kv) => { |
| 92 | + let mut hmap = serde_json::Map::new(); |
| 93 | + for (key, v) in kv.iter() { |
| 94 | + let json_val = gson_to_json(v)?; |
| 95 | + hmap.insert(key.to_owned(), json_val); |
| 96 | + } |
| 97 | + JsonValue::Object(hmap) |
| 98 | + } |
| 99 | + }; |
| 100 | + Ok(v) |
| 101 | +} |
0 commit comments