net_file/jsons/
json_parser.rs

1use std::str::from_utf8;
2
3use chrono::{DateTime, Utc, NaiveDateTime};
4use jsonpath_rust::JsonPathFinder;
5use serde_json::Value;
6use unescape::unescape;
7
8pub struct JsonParser;
9
10impl JsonParser {
11    pub fn find(json_binary: &[u8], path: &str) -> Value {
12        let json = from_utf8(json_binary).unwrap();
13        let finder = JsonPathFinder::from_str(json, path).expect("path not found");
14
15        finder.find()
16    }
17    pub fn first(value: &Value) -> Option<&Value> {
18        let value_json = value.as_array().unwrap();
19        if value_json.len() > 1 {
20            panic!("currently supported only one packet in the file: CU-861mdc6t7")
21        }
22
23        value_json.first()
24    }
25
26    pub fn print(json_path_value: &Value) -> String {
27        format!("{}", json_path_value)
28    }
29
30    pub fn pretty(json_path_value: &Value) -> String {
31        format!("{:#}", json_path_value)
32    }
33
34    pub fn get_vec(json_path_value: Value) -> Vec<u8> {
35        serde_json::to_vec(&json_path_value).unwrap()
36    }
37
38    pub fn get_string(mut json_path_value: Value) -> String {
39        let value = json_path_value.get_mut(0).take()
40            .expect("value not found");
41
42        unescape(value.as_str().unwrap()).unwrap()
43    }
44
45    pub fn get_utc_frame_time(json_path_value: Value) -> DateTime<Utc> {
46        const FORMAT_STR: &str = "%b %d, %Y %H:%M:%S.%f %Z";
47        let datetime_str = Self::get_string(json_path_value);
48        NaiveDateTime::parse_from_str(&datetime_str, FORMAT_STR).unwrap().and_utc()
49    }
50
51    pub fn get_utc_timestamp_millis(json_path_value: Value) -> i64 {
52        let path_value = JsonParser::get_string(json_path_value);
53        let timestamp: Vec<&str> = path_value
54            .split('.')
55            .collect();
56        let fraction = &timestamp.get(1).unwrap()[0..3];
57        format!("{}{}", &timestamp.first().unwrap(), fraction).parse::<i64>().unwrap()
58    }
59
60    pub fn get_utc_timestamp_nanos(json_path_value: Value) -> i64 {
61        let value_str: String = JsonParser::get_string(json_path_value).split('.').collect();
62
63        value_str.parse::<i64>().unwrap()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use chrono::NaiveDateTime;
70
71    use crate::file::files::Files;
72    use crate::jsons::json_pcap_parser::PATH_FRAME_TIME_EPOCH;
73    use crate::test_resources;
74
75    use super::*;
76
77    #[test]
78    fn expected_extract_layer() {
79        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
80        let json_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted.json"));
81
82        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
83        let json = JsonParser::print(&result);
84
85        assert_eq!(json, from_utf8(&json_buffer).unwrap());
86    }
87
88    #[test]
89    #[should_panic]
90    fn support_only_one_packet_in_file() {
91        let pcap_buffer = Files::read_vector(test_resources!("captures/dhcp.pcap"));
92
93        let value = JsonParser::find(&pcap_buffer, "$.._source.layers");
94        JsonParser::first(&value);
95    }
96
97    #[test]
98    fn expected_extract_layer_pretty() {
99        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
100        let json_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
101
102        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
103        let json = JsonParser::pretty(&result);
104
105        assert_eq!(json, from_utf8(&json_buffer).unwrap());
106    }
107
108    #[test]
109    fn expected_extract_frame_time() {
110        let pcap_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
111
112        let result = JsonParser::find(&pcap_buffer, "$..frame['frame.time']");
113        let time = JsonParser::get_string(result);
114
115        assert_eq!(time, "Sep 18, 2013 04:49:07.000000000 UTC");
116    }
117
118    #[test]
119    fn expected_get_utc_timestamp_millis() {
120        const EXPECTED_TIME: i64 = 1379479747000;
121
122        let pcap_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
123        let value = JsonParser::find(&pcap_buffer, PATH_FRAME_TIME_EPOCH);
124        let result = JsonParser::get_utc_timestamp_millis(value);
125
126        assert_eq!(result, EXPECTED_TIME)
127    }
128
129    #[test]
130    fn expected_get_utc_timestamp_nanos() {
131        const EXPECTED_TIME: i64 = 1379479747000000000;
132
133        let pcap_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
134        let value = JsonParser::find(&pcap_buffer, PATH_FRAME_TIME_EPOCH);
135        let result = JsonParser::get_utc_timestamp_nanos(value);
136
137        assert_eq!(result, EXPECTED_TIME)
138    }
139
140    #[test]
141    fn expected_get_utc_timestamp_nanos_2() {
142        const EXPECTED_TIME: i64 = 1688714981480935000;
143
144        let pcap_buffer = Files::read_vector(test_resources!("captures/epoch_frame_time.json"));
145        let value = JsonParser::find(&pcap_buffer, PATH_FRAME_TIME_EPOCH);
146        let result = JsonParser::get_utc_timestamp_nanos(value);
147
148        assert_eq!(result, EXPECTED_TIME)
149    }
150
151    #[test]
152    #[should_panic]
153    fn panic_if_unknown_path() {
154        let pcap_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
155
156        let unknown_path = "";
157        JsonParser::find(&pcap_buffer, unknown_path);
158    }
159
160    #[test]
161    #[should_panic]
162    fn panic_if_value_not_found() {
163        let pcap_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
164
165        let unknown_path = "$..frame1";
166        let result = JsonParser::find(&pcap_buffer, unknown_path);
167        JsonParser::get_string(result);
168    }
169
170    #[test]
171    fn expected_extract_layer_and_return_vec() {
172        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
173        let json_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted.json"));
174
175        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
176        let json = JsonParser::get_vec(result);
177
178        assert_eq!(json, json_buffer);
179    }
180
181    #[test]
182    fn expected_convert_frame_time_to_date_time() {
183        let time = NaiveDateTime::parse_from_str("Sat, 11 Feb 2023 23:40:00.000000000 UTC", "%a, %d %b %Y %H:%M:%S.%f %Z").unwrap().and_utc();
184        println!("{:?}", time);
185
186        let time = NaiveDateTime::parse_from_str("Sep 18, 2013 07:49:07.000000000 EEST", "%b %d, %Y %H:%M:%S.%f %Z").unwrap().and_utc();
187        println!("{:?}", time);
188
189        let time = NaiveDateTime::parse_from_str("Dec  5, 2004 21:16:24.317453000 EET", "%b %d, %Y %H:%M:%S.%f %Z").unwrap().and_utc();
190        println!("{:?}", time);
191
192        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
193        let result = JsonParser::find(&pcap_buffer, "$..frame['frame.time']");
194        let time = JsonParser::get_utc_frame_time(result);
195        println!("{:?}", time);
196        assert_eq!(time.to_string(), "2013-09-18 04:49:07 UTC".to_string());
197    }
198}