1use std::collections::HashMap;
24use std::sync::Arc;
25
26use super::descriptor::{Cardinality, FieldDescriptor, Kind, MessageDescriptor};
27use super::dynamic::{is_field_value_default, DynamicMessage};
28use super::value::{MapKey, Value};
29#[derive(Debug)]
37pub enum JsonError {
38 InvalidJson(serde_json::Error),
40 Schema(String),
42 UnknownEnumValue(String),
44}
45
46impl std::fmt::Display for JsonError {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 match self {
49 JsonError::InvalidJson(e) => write!(f, "invalid JSON: {e}"),
50 JsonError::Schema(s) => write!(f, "schema mismatch: {s}"),
51 JsonError::UnknownEnumValue(s) => write!(f, "unknown enum value: {s}"),
52 }
53 }
54}
55
56impl std::error::Error for JsonError {
57 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
58 match self {
59 JsonError::InvalidJson(e) => Some(e),
60 _ => None,
61 }
62 }
63}
64
65impl From<JsonError> for crate::ReflectError {
66 fn from(e: JsonError) -> Self {
67 crate::ReflectError::Field(e.to_string())
68 }
69}
70
71impl DynamicMessage {
76 pub fn to_json(&self) -> Result<serde_json::Value, JsonError> {
86 encode_message(self)
87 }
88
89 pub fn to_json_string(&self) -> Result<String, JsonError> {
95 let v = self.to_json()?;
96 serde_json::to_string(&v).map_err(JsonError::InvalidJson)
97 }
98
99 pub fn from_json(desc: MessageDescriptor, json: &serde_json::Value) -> Result<Self, JsonError> {
109 decode_message(desc, json)
110 }
111
112 pub fn from_json_str(desc: MessageDescriptor, s: &str) -> Result<Self, JsonError> {
120 let json: serde_json::Value = serde_json::from_str(s).map_err(JsonError::InvalidJson)?;
121 decode_message(desc, &json)
122 }
123}
124
125fn encode_message(msg: &DynamicMessage) -> Result<serde_json::Value, JsonError> {
130 let mut map = serde_json::Map::new();
131 let desc = msg.descriptor();
132
133 for field in desc.fields() {
134 let value = msg.get_field(&field);
135 if is_field_value_default(&field, &value) {
137 continue;
138 }
139 let json_value = encode_field_value(&value, &field)?;
140 map.insert(field.json_name().to_owned(), json_value);
141 }
142
143 Ok(serde_json::Value::Object(map))
144}
145
146fn encode_field_value(
147 value: &Value,
148 field: &FieldDescriptor,
149) -> Result<serde_json::Value, JsonError> {
150 if field.is_map() {
151 return encode_map(value, field);
152 }
153 if matches!(field.cardinality(), Cardinality::Repeated) {
154 return encode_list(value, field);
155 }
156 encode_singular(value, field)
157}
158
159fn encode_list(value: &Value, field: &FieldDescriptor) -> Result<serde_json::Value, JsonError> {
160 match value {
161 Value::List(items) => {
162 let mut arr = Vec::with_capacity(items.len());
163 for item in items {
164 arr.push(encode_singular(item, field)?);
165 }
166 Ok(serde_json::Value::Array(arr))
167 }
168 other => Err(JsonError::Schema(format!(
169 "expected list for repeated field '{}', got {:?}",
170 field.name(),
171 other
172 ))),
173 }
174}
175
176fn encode_map(value: &Value, field: &FieldDescriptor) -> Result<serde_json::Value, JsonError> {
177 match value {
178 Value::Map(entries) => {
179 let val_field = field.map_entry_value_field().ok_or_else(|| {
180 JsonError::Schema(format!(
181 "map field '{}' missing value field descriptor",
182 field.name()
183 ))
184 })?;
185 let mut obj = serde_json::Map::new();
186 let mut sorted: Vec<_> = entries.iter().collect();
188 sorted.sort_by_key(|(k, _)| map_key_to_string(k));
189 for (k, v) in sorted {
190 obj.insert(map_key_to_string(k), encode_singular(v, &val_field)?);
191 }
192 Ok(serde_json::Value::Object(obj))
193 }
194 other => Err(JsonError::Schema(format!(
195 "expected map for map field '{}', got {:?}",
196 field.name(),
197 other
198 ))),
199 }
200}
201
202fn encode_singular(value: &Value, field: &FieldDescriptor) -> Result<serde_json::Value, JsonError> {
204 match value {
205 Value::F64(v) => encode_f64(*v),
206 Value::F32(v) => encode_f64(f64::from(*v)),
207 Value::I32(v) => Ok(serde_json::json!(*v)),
208 Value::U32(v) => Ok(serde_json::json!(*v)),
209 Value::I64(v) => Ok(serde_json::Value::String(v.to_string())),
211 Value::U64(v) => Ok(serde_json::Value::String(v.to_string())),
212 Value::Bool(v) => Ok(serde_json::Value::Bool(*v)),
213 Value::String(s) => Ok(serde_json::Value::String(s.clone())),
214 Value::Bytes(b) => encode_bytes(b),
215 Value::EnumNumber(n) => encode_enum_number(*n, field),
216 Value::Message(m) => encode_message(m),
217 Value::List(_) | Value::Map(_) => Err(JsonError::Schema(format!(
218 "unexpected list/map in singular context for field '{}'",
219 field.name()
220 ))),
221 }
222}
223
224fn encode_f64(v: f64) -> Result<serde_json::Value, JsonError> {
225 if v.is_nan() {
226 return Ok(serde_json::Value::String("NaN".to_owned()));
227 }
228 if v.is_infinite() {
229 let s = if v > 0.0 { "Infinity" } else { "-Infinity" };
230 return Ok(serde_json::Value::String(s.to_owned()));
231 }
232 serde_json::Number::from_f64(v)
233 .map(serde_json::Value::Number)
234 .ok_or_else(|| JsonError::Schema(format!("cannot represent f64 as JSON number: {v}")))
235}
236
237fn encode_bytes(b: &[u8]) -> Result<serde_json::Value, JsonError> {
238 use base64::Engine as _;
239 Ok(serde_json::Value::String(
240 base64::engine::general_purpose::STANDARD.encode(b),
241 ))
242}
243
244fn encode_enum_number(n: i32, field: &FieldDescriptor) -> Result<serde_json::Value, JsonError> {
245 if let Some(enum_desc) = field.enum_type() {
247 if let Some(val_desc) = enum_desc.get_value(n) {
248 return Ok(serde_json::Value::String(val_desc.name().to_owned()));
249 }
250 }
251 Ok(serde_json::json!(n))
253}
254
255fn map_key_to_string(key: &MapKey) -> String {
256 match key {
257 MapKey::String(s) => s.clone(),
258 MapKey::I32(v) => v.to_string(),
259 MapKey::I64(v) => v.to_string(),
260 MapKey::U32(v) => v.to_string(),
261 MapKey::U64(v) => v.to_string(),
262 MapKey::Bool(v) => if *v { "true" } else { "false" }.to_owned(),
263 }
264}
265
266fn decode_message(
271 desc: MessageDescriptor,
272 json: &serde_json::Value,
273) -> Result<DynamicMessage, JsonError> {
274 let obj = match json {
275 serde_json::Value::Object(m) => m,
276 serde_json::Value::Null => return Ok(DynamicMessage::new(desc)),
278 other => {
279 return Err(JsonError::Schema(format!(
280 "expected JSON object for message, got {}",
281 json_type_name(other)
282 )));
283 }
284 };
285
286 let mut msg = DynamicMessage::new(desc.clone());
287
288 for (json_key, json_val) in obj {
289 let field = desc
291 .get_field_by_json_name(json_key)
292 .or_else(|| desc.get_field_by_name(json_key));
293
294 let field = match field {
295 Some(f) => f,
296 None => continue,
298 };
299
300 if json_val.is_null() {
302 continue;
303 }
304
305 let value = decode_field_value(json_val, &field)?;
306 msg.set_field(&field, value);
307 }
308
309 Ok(msg)
310}
311
312fn decode_field_value(
313 json: &serde_json::Value,
314 field: &FieldDescriptor,
315) -> Result<Value, JsonError> {
316 if field.is_map() {
317 return decode_map(json, field);
318 }
319 if matches!(field.cardinality(), Cardinality::Repeated) {
320 return decode_list(json, field);
321 }
322 decode_singular(json, field)
323}
324
325fn decode_list(json: &serde_json::Value, field: &FieldDescriptor) -> Result<Value, JsonError> {
326 let arr = match json {
327 serde_json::Value::Array(a) => a,
328 other => {
329 return Err(JsonError::Schema(format!(
330 "expected JSON array for repeated field '{}', got {}",
331 field.name(),
332 json_type_name(other)
333 )));
334 }
335 };
336 let mut items = Vec::with_capacity(arr.len());
337 for item in arr {
338 items.push(decode_singular(item, field)?);
339 }
340 Ok(Value::List(items))
341}
342
343fn decode_map(json: &serde_json::Value, field: &FieldDescriptor) -> Result<Value, JsonError> {
344 let obj = match json {
345 serde_json::Value::Object(o) => o,
346 other => {
347 return Err(JsonError::Schema(format!(
348 "expected JSON object for map field '{}', got {}",
349 field.name(),
350 json_type_name(other)
351 )));
352 }
353 };
354
355 let key_field = field.map_entry_key_field().ok_or_else(|| {
356 JsonError::Schema(format!(
357 "map field '{}' missing key field descriptor",
358 field.name()
359 ))
360 })?;
361 let val_field = field.map_entry_value_field().ok_or_else(|| {
362 JsonError::Schema(format!(
363 "map field '{}' missing value field descriptor",
364 field.name()
365 ))
366 })?;
367
368 let mut map = HashMap::new();
369 for (k_str, v_json) in obj {
370 let map_key = parse_map_key(k_str, key_field.kind())?;
371 let map_val = decode_singular(v_json, &val_field)?;
372 map.insert(map_key, map_val);
373 }
374 Ok(Value::Map(map))
375}
376
377fn parse_map_key(s: &str, kind: Kind) -> Result<MapKey, JsonError> {
378 match kind {
379 Kind::String => Ok(MapKey::String(s.to_owned())),
380 Kind::Bool => match s {
381 "true" => Ok(MapKey::Bool(true)),
382 "false" => Ok(MapKey::Bool(false)),
383 other => Err(JsonError::Schema(format!("invalid bool map key: {other}"))),
384 },
385 Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => s
386 .parse::<i32>()
387 .map(MapKey::I32)
388 .map_err(|_| JsonError::Schema(format!("invalid int32 map key: {s}"))),
389 Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => s
390 .parse::<i64>()
391 .map(MapKey::I64)
392 .map_err(|_| JsonError::Schema(format!("invalid int64 map key: {s}"))),
393 Kind::Uint32 | Kind::Fixed32 => s
394 .parse::<u32>()
395 .map(MapKey::U32)
396 .map_err(|_| JsonError::Schema(format!("invalid uint32 map key: {s}"))),
397 Kind::Uint64 | Kind::Fixed64 => s
398 .parse::<u64>()
399 .map(MapKey::U64)
400 .map_err(|_| JsonError::Schema(format!("invalid uint64 map key: {s}"))),
401 other => Err(JsonError::Schema(format!(
402 "unsupported map key kind: {other:?}"
403 ))),
404 }
405}
406
407fn decode_singular(json: &serde_json::Value, field: &FieldDescriptor) -> Result<Value, JsonError> {
410 match field.kind() {
411 Kind::Double => decode_f64(json),
412 Kind::Float => decode_f32(json),
413 Kind::Int32 | Kind::Sint32 | Kind::Sfixed32 => decode_i32(json),
414 Kind::Int64 | Kind::Sint64 | Kind::Sfixed64 => decode_i64(json),
415 Kind::Uint32 | Kind::Fixed32 => decode_u32(json),
416 Kind::Uint64 | Kind::Fixed64 => decode_u64(json),
417 Kind::Bool => decode_bool(json),
418 Kind::String => decode_string_val(json),
419 Kind::Bytes => decode_bytes_val(json),
420 Kind::Enum(_) => decode_enum(json, field),
421 Kind::Message(msg_index) => {
422 if json.is_null() {
423 let msg_desc = MessageDescriptor {
424 pool: Arc::clone(&field.pool),
425 index: msg_index,
426 };
427 return Ok(Value::Message(Box::new(DynamicMessage::new(msg_desc))));
428 }
429 let msg_desc = MessageDescriptor {
430 pool: Arc::clone(&field.pool),
431 index: msg_index,
432 };
433 Ok(Value::Message(Box::new(decode_message(msg_desc, json)?)))
434 }
435 Kind::Group(_) => Err(JsonError::Schema(
436 "group fields are not supported in JSON".to_owned(),
437 )),
438 }
439}
440
441fn decode_f64(json: &serde_json::Value) -> Result<Value, JsonError> {
442 match json {
443 serde_json::Value::Number(n) => {
444 Ok(Value::F64(n.as_f64().ok_or_else(|| {
445 JsonError::Schema("number out of f64 range".to_owned())
446 })?))
447 }
448 serde_json::Value::String(s) => match s.as_str() {
449 "NaN" => Ok(Value::F64(f64::NAN)),
450 "Infinity" => Ok(Value::F64(f64::INFINITY)),
451 "-Infinity" => Ok(Value::F64(f64::NEG_INFINITY)),
452 other => other
453 .parse::<f64>()
454 .map(Value::F64)
455 .map_err(|_| JsonError::Schema(format!("invalid f64 string: {other}"))),
456 },
457 other => Err(type_mismatch("f64", other)),
458 }
459}
460
461fn decode_f32(json: &serde_json::Value) -> Result<Value, JsonError> {
462 match json {
463 serde_json::Value::Number(n) => {
464 Ok(Value::F32(n.as_f64().map(|v| v as f32).ok_or_else(
465 || JsonError::Schema("number out of range for f32".to_owned()),
466 )?))
467 }
468 serde_json::Value::String(s) => match s.as_str() {
469 "NaN" => Ok(Value::F32(f32::NAN)),
470 "Infinity" => Ok(Value::F32(f32::INFINITY)),
471 "-Infinity" => Ok(Value::F32(f32::NEG_INFINITY)),
472 other => other
473 .parse::<f32>()
474 .map(Value::F32)
475 .map_err(|_| JsonError::Schema(format!("invalid f32 string: {other}"))),
476 },
477 other => Err(type_mismatch("f32", other)),
478 }
479}
480
481fn decode_i32(json: &serde_json::Value) -> Result<Value, JsonError> {
482 match json {
483 serde_json::Value::Number(n) => n
484 .as_i64()
485 .and_then(|v| i32::try_from(v).ok())
486 .map(Value::I32)
487 .ok_or_else(|| JsonError::Schema(format!("value out of i32 range: {n}"))),
488 serde_json::Value::String(s) => s
489 .parse::<i32>()
490 .map(Value::I32)
491 .map_err(|_| JsonError::Schema(format!("invalid i32 string: {s}"))),
492 other => Err(type_mismatch("i32", other)),
493 }
494}
495
496fn decode_i64(json: &serde_json::Value) -> Result<Value, JsonError> {
497 match json {
498 serde_json::Value::Number(n) => n
499 .as_i64()
500 .map(Value::I64)
501 .ok_or_else(|| JsonError::Schema(format!("value out of i64 range: {n}"))),
502 serde_json::Value::String(s) => s
503 .parse::<i64>()
504 .map(Value::I64)
505 .map_err(|_| JsonError::Schema(format!("invalid i64 string: {s}"))),
506 other => Err(type_mismatch("i64", other)),
507 }
508}
509
510fn decode_u32(json: &serde_json::Value) -> Result<Value, JsonError> {
511 match json {
512 serde_json::Value::Number(n) => n
513 .as_u64()
514 .and_then(|v| u32::try_from(v).ok())
515 .map(Value::U32)
516 .ok_or_else(|| JsonError::Schema(format!("value out of u32 range: {n}"))),
517 serde_json::Value::String(s) => s
518 .parse::<u32>()
519 .map(Value::U32)
520 .map_err(|_| JsonError::Schema(format!("invalid u32 string: {s}"))),
521 other => Err(type_mismatch("u32", other)),
522 }
523}
524
525fn decode_u64(json: &serde_json::Value) -> Result<Value, JsonError> {
526 match json {
527 serde_json::Value::Number(n) => n
528 .as_u64()
529 .map(Value::U64)
530 .ok_or_else(|| JsonError::Schema(format!("value out of u64 range: {n}"))),
531 serde_json::Value::String(s) => s
532 .parse::<u64>()
533 .map(Value::U64)
534 .map_err(|_| JsonError::Schema(format!("invalid u64 string: {s}"))),
535 other => Err(type_mismatch("u64", other)),
536 }
537}
538
539fn decode_bool(json: &serde_json::Value) -> Result<Value, JsonError> {
540 match json {
541 serde_json::Value::Bool(b) => Ok(Value::Bool(*b)),
542 serde_json::Value::String(s) => match s.as_str() {
543 "true" => Ok(Value::Bool(true)),
544 "false" => Ok(Value::Bool(false)),
545 other => Err(JsonError::Schema(format!("invalid bool string: {other}"))),
546 },
547 other => Err(type_mismatch("bool", other)),
548 }
549}
550
551fn decode_string_val(json: &serde_json::Value) -> Result<Value, JsonError> {
552 match json {
553 serde_json::Value::String(s) => Ok(Value::String(s.clone())),
554 other => Err(type_mismatch("string", other)),
555 }
556}
557
558fn decode_bytes_val(json: &serde_json::Value) -> Result<Value, JsonError> {
559 match json {
560 serde_json::Value::String(s) => {
561 use base64::Engine as _;
562 let bytes = base64::engine::general_purpose::STANDARD
564 .decode(s)
565 .or_else(|_| {
566 base64::engine::general_purpose::STANDARD_NO_PAD.decode(s.trim_end_matches('='))
567 })
568 .or_else(|_| base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(s))
569 .map_err(|e| JsonError::Schema(format!("invalid base64 for bytes field: {e}")))?;
570 Ok(Value::Bytes(bytes))
571 }
572 other => Err(type_mismatch("bytes (base64 string)", other)),
573 }
574}
575
576fn decode_enum(json: &serde_json::Value, field: &FieldDescriptor) -> Result<Value, JsonError> {
577 let enum_desc = field.enum_type().ok_or_else(|| {
578 JsonError::Schema(format!(
579 "field '{}' has enum kind but no enum descriptor",
580 field.name()
581 ))
582 })?;
583
584 match json {
585 serde_json::Value::Number(n) => {
586 let num = n
587 .as_i64()
588 .and_then(|v| i32::try_from(v).ok())
589 .ok_or_else(|| JsonError::Schema(format!("enum number out of i32 range: {n}")))?;
590 Ok(Value::EnumNumber(num))
591 }
592 serde_json::Value::String(s) => enum_desc
593 .get_value_by_name(s)
594 .map(|v| Value::EnumNumber(v.number()))
595 .ok_or_else(|| JsonError::UnknownEnumValue(s.clone())),
596 other => Err(type_mismatch("enum (number or name string)", other)),
597 }
598}
599
600fn json_type_name(v: &serde_json::Value) -> &'static str {
605 match v {
606 serde_json::Value::Null => "null",
607 serde_json::Value::Bool(_) => "bool",
608 serde_json::Value::Number(_) => "number",
609 serde_json::Value::String(_) => "string",
610 serde_json::Value::Array(_) => "array",
611 serde_json::Value::Object(_) => "object",
612 }
613}
614
615fn type_mismatch(expected: &str, got: &serde_json::Value) -> JsonError {
616 JsonError::Schema(format!("expected {expected}, got {}", json_type_name(got)))
617}