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
use crate::{error::Error, *}; use quick_xml::{events::*, Writer}; use serde_json::Value; use std::io::Cursor; fn is_attribute_property_name(name: &str) -> bool { name.find(ATTRIBUTE_START_CHARACTER) == Some(0) } fn write_value(writer: &mut Writer<Cursor<Vec<u8>>>, value: Value) -> Result<(), Error> { match value { Value::Null => return Err(Error::JsonParseUnexpectedNull), Value::Bool(_) => return Err(Error::JsonParseUnexpectedBool), Value::Number(_) => return Err(Error::JsonParseUnexpectedNumber), Value::String(string) => { writer .write_event(Event::Text(BytesText::from_plain_str(&string))) .map_err(|e| Error::XmlQuickXmlError(e))?; } Value::Array(_) => return Err(Error::JsonParseUnexpectedArray), Value::Object(map) => { for (key, value) in map { if is_attribute_property_name(&key) { continue; } match value { Value::String(_) => write_value(writer, value)?, Value::Array(values) => { for value in values { let has_children = match &value { Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => false, Value::Array(array) => array.is_empty(), Value::Object(object) => object .iter() .find(|(key, _)| !is_attribute_property_name(key)) .is_some(), }; let mut bytes_start = BytesStart::borrowed(key.as_bytes(), key.len()); match &value { Value::Object(object) => { for (key, value) in object.iter() { if is_attribute_property_name(key) { bytes_start.push_attribute(( key.get(1..) .ok_or(Error::JsonParseInvalidAttributeName)?, match value { Value::String(string) => string, _ => { return Err( Error::JsonParseInvalidAttributeValue, ) } } .as_str(), )); } } } _ => return Err(Error::JsonParseExpectedObject), } if !has_children { writer .write_event(Event::Empty(bytes_start)) .map_err(|e| Error::XmlQuickXmlError(e))?; } else { writer .write_event(Event::Start(bytes_start)) .map_err(|e| Error::XmlQuickXmlError(e))?; write_value(writer, value)?; writer .write_event(Event::End(BytesEnd::borrowed(key.as_bytes()))) .map_err(|e| Error::XmlQuickXmlError(e))?; } } } _ => return Err(Error::JsonParseExpectedArray), } } } } Ok(()) } pub fn json_to_xml(json: &str, indent: Option<(u8, usize)>) -> Result<String, Error> { let mut writer = match indent { None => Writer::new(Cursor::new(Vec::new())), Some((c, size)) => Writer::new_with_indent(Cursor::new(vec![]), c, size), }; write_value( &mut writer, serde_json::from_str(json).map_err(|e| Error::JsonParseError(e))?, )?; bytes_to_string(&writer.into_inner().into_inner()) }