pb_to_json/
lib.rs

1#![doc = include_str!("../README.md")]
2
3/// Converts a protocol buffer string to a JSON string.
4///
5/// The function takes a protocol buffer string as input and returns the corresponding JSON string.
6/// It supports nested objects, repeated fields, and key-value pairs of different types (string, number, boolean).
7///
8/// # Examples
9///
10/// ```
11/// use pb_to_json::convert_pb_to_json;
12/// 
13/// let pb_string = r#"
14///     name: "John Doe"
15///     age: 30
16///     city: "New York"
17/// "#;
18///
19/// let json_string = convert_pb_to_json(pb_string);
20/// println!("{}", json_string);
21/// ```
22///
23/// The above example will output:
24/// ```json
25/// {
26///     "name": "John Doe",
27///     "age": "30",
28///     "city": "New York"
29/// }
30/// ```
31pub fn convert_pb_to_json(pb_string: &str) -> String {
32    let mut data = serde_json::Map::new();
33    let mut current_object: Option<serde_json::Map<String, serde_json::Value>> = None;
34    let mut current_key = String::new();
35
36    for line in pb_string.lines() {
37        let line = line.trim();
38        if line.is_empty() {
39            continue;
40        }
41
42        // check if the line ends with "{", indicating the start of a nested object
43        if line.ends_with("{") {
44            current_key = line[..line.len() - 2].trim().to_string();
45            current_object = Some(serde_json::Map::new());
46        } else if line == "}" {
47            if let Some(obj) = current_object.take() {
48                data.insert(current_key.clone(), serde_json::Value::Object(obj));
49            }
50        } else {
51            let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
52            
53            // skip the line if it doesn't have exactly two parts (key and value)
54            if parts.len() != 2 {
55                continue;
56            }
57
58            let key = parts[0].trim();
59            let value = parts[1].trim().trim_matches('"');
60
61            if let Some(ref mut obj) = current_object {
62                obj.insert(key.to_string(), serde_json::Value::String(value.to_string()));
63            } else if data.contains_key(key) {
64                if let Some(serde_json::Value::Array(ref mut arr)) = data.get_mut(key) {
65                    arr.push(serde_json::Value::String(value.to_string()));
66                } else {
67                    let mut arr = Vec::new();
68                    arr.push(data[key].clone());
69                    arr.push(serde_json::Value::String(value.to_string()));
70                    data.insert(key.to_string(), serde_json::Value::Array(arr));
71                }
72            } else {
73                data.insert(key.to_string(), serde_json::Value::String(value.to_string()));
74            }
75        }
76    }
77
78    serde_json::to_string_pretty(&data).unwrap()
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_simple_pb() {
87        let pb_string = r#"
88            name: "John Doe"
89            age: 30
90            city: "New York"
91        "#;
92
93        let expected_json = r#"{
94            "name": "John Doe",
95            "age": "30",
96            "city": "New York"
97        }"#;
98
99        let actual_json = convert_pb_to_json(pb_string);
100        assert_eq!(normalize_json(expected_json), normalize_json(&actual_json));
101    }
102
103    #[test]
104    fn test_nested_pb() {
105        let pb_string = r#"
106            name: "Alice"
107            address {
108                street: "123 Main St"
109                city: "London"
110                country: "UK"
111            }
112            phone_numbers: "1234567890"
113            phone_numbers: "9876543210"
114        "#;
115
116        let expected_json = r#"{
117            "name": "Alice",
118            "address": {
119                "street": "123 Main St",
120                "city": "London",
121                "country": "UK"
122            },
123            "phone_numbers": [
124                "1234567890",
125                "9876543210"
126            ]
127        }"#;
128
129        let actual_json = convert_pb_to_json(pb_string);
130        assert_eq!(normalize_json(expected_json), normalize_json(&actual_json));
131    }
132
133    #[test]
134    fn test_empty_pb() {
135        let pb_string = "";
136        let expected_json = "{}";
137
138        let actual_json = convert_pb_to_json(pb_string);
139        assert_eq!(expected_json, actual_json);
140    }
141
142    fn normalize_json(json: &str) -> String {
143        let parsed: serde_json::Value = serde_json::from_str(json).unwrap();
144        serde_json::to_string_pretty(&parsed).unwrap()
145    }
146}