1use std::io::Write;
4
5use crate::DicomJson;
6use dicom_core::{
7 header::Header, value::PixelFragmentSequence, DicomValue, PrimitiveValue, Tag, VR,
8};
9use dicom_dictionary_std::StandardDataDictionary;
10use dicom_object::{mem::InMemElement, DefaultDicomObject, InMemDicomObject};
11use serde::{ser::SerializeMap, Serialize, Serializer};
12
13use self::value::{AsNumbers, AsPersonNames, AsStrings, InlineBinary};
14mod value;
15
16pub fn to_string<T>(data: T) -> Result<String, serde_json::Error>
18where
19 DicomJson<T>: From<T> + Serialize,
20{
21 serde_json::to_string(&DicomJson::from(data))
22}
23
24pub fn to_string_pretty<T>(data: T) -> Result<String, serde_json::Error>
26where
27 DicomJson<T>: From<T> + Serialize,
28{
29 serde_json::to_string_pretty(&DicomJson::from(data))
30}
31
32pub fn to_value<T>(data: T) -> Result<serde_json::Value, serde_json::Error>
34where
35 DicomJson<T>: From<T> + Serialize,
36{
37 serde_json::to_value(DicomJson::from(data))
38}
39
40pub fn to_vec<T>(data: T) -> Result<Vec<u8>, serde_json::Error>
42where
43 DicomJson<T>: From<T> + Serialize,
44{
45 serde_json::to_vec(&DicomJson::from(data))
46}
47
48pub fn to_writer<W, T>(writer: W, data: T) -> Result<(), serde_json::Error>
50where
51 DicomJson<T>: From<T> + Serialize,
52 W: Write,
53{
54 serde_json::to_writer(writer, &DicomJson::from(data))
55}
56
57impl<'a, D> From<&'a DefaultDicomObject<D>> for DicomJson<&'a DefaultDicomObject<D>> {
58 fn from(value: &'a DefaultDicomObject<D>) -> Self {
59 Self(value)
60 }
61}
62
63impl<'a, D> Serialize for DicomJson<&'a DefaultDicomObject<D>>
64where
65 D: 'a,
66{
67 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: Serializer,
77 {
78 let mut ser = serializer.serialize_map(None)?;
79
80 for e in self.0.meta().to_element_iter() {
81 let tag = e.tag();
82 let DicomValue::Primitive(value) = e.value() else {
83 continue;
84 };
85 let e = InMemElement::<StandardDataDictionary>::new(e.tag(), e.vr(), value.clone());
86 ser.serialize_entry(&DicomJson(tag), &DicomJson(&e))?;
87 }
88
89 let inner: &InMemDicomObject<_> = &**self.0;
90 for e in inner {
91 let tag = e.tag();
92 ser.serialize_entry(&DicomJson(tag), &DicomJson(e))?;
93 }
94
95 ser.end()
96 }
97}
98
99impl<D> From<DefaultDicomObject<D>> for DicomJson<DefaultDicomObject<D>> {
100 fn from(value: DefaultDicomObject<D>) -> Self {
101 Self(value)
102 }
103}
104
105impl<D> Serialize for DicomJson<DefaultDicomObject<D>> {
106 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
114 where
115 S: Serializer,
116 {
117 DicomJson(&self.0).serialize(serializer)
118 }
119}
120
121impl<'a, D> From<&'a InMemDicomObject<D>> for DicomJson<&'a InMemDicomObject<D>> {
122 fn from(value: &'a InMemDicomObject<D>) -> Self {
123 Self(value)
124 }
125}
126
127impl<'a, D> Serialize for DicomJson<&'a InMemDicomObject<D>>
128where
129 D: 'a,
130{
131 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
135 where
136 S: Serializer,
137 {
138 serializer.collect_map(self.0.into_iter().map(|e| {
139 let tag = e.tag();
140 (DicomJson(tag), DicomJson(e))
141 }))
142 }
143}
144
145impl<D> From<InMemDicomObject<D>> for DicomJson<InMemDicomObject<D>> {
146 fn from(value: InMemDicomObject<D>) -> Self {
147 Self(value)
148 }
149}
150
151impl<D> Serialize for DicomJson<InMemDicomObject<D>> {
152 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
153 where
154 S: Serializer,
155 {
156 DicomJson(&self.0).serialize(serializer)
157 }
158}
159
160impl<'a, D> From<&'a [InMemDicomObject<D>]> for DicomJson<&'a [InMemDicomObject<D>]> {
161 fn from(value: &'a [InMemDicomObject<D>]) -> Self {
162 Self(value)
163 }
164}
165
166impl<D> Serialize for DicomJson<&'_ [InMemDicomObject<D>]> {
167 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
169 where
170 S: Serializer,
171 {
172 serializer.collect_seq(self.0.iter().map(DicomJson::from))
173 }
174}
175
176impl<D> From<Vec<InMemDicomObject<D>>> for DicomJson<Vec<InMemDicomObject<D>>> {
177 fn from(value: Vec<InMemDicomObject<D>>) -> Self {
178 Self(value)
179 }
180}
181
182impl<D> Serialize for DicomJson<Vec<InMemDicomObject<D>>> {
183 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185 where
186 S: Serializer,
187 {
188 DicomJson(self.0.as_slice()).serialize(serializer)
189 }
190}
191
192impl<'a, D> From<&'a InMemElement<D>> for DicomJson<&'a InMemElement<D>> {
193 fn from(value: &'a InMemElement<D>) -> Self {
194 Self(value)
195 }
196}
197
198impl<D> Serialize for DicomJson<&'_ InMemElement<D>> {
199 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
210 where
211 S: Serializer,
212 {
213 let mut serializer = serializer.serialize_map(None)?;
214 let vr = self.0.vr();
215 serializer.serialize_entry("vr", vr.to_string())?;
216
217 match self.0.value() {
218 DicomValue::Sequence(seq) => {
219 serializer.serialize_entry("Value", &DicomJson(seq.items()))?;
220 }
221 DicomValue::PixelSequence(_seq) => {
222 }
224 DicomValue::Primitive(PrimitiveValue::Empty) => {
225 }
227 DicomValue::Primitive(v) => match vr {
228 VR::AE
229 | VR::AS
230 | VR::AT
231 | VR::CS
232 | VR::DA
233 | VR::DT
234 | VR::LO
235 | VR::LT
236 | VR::SH
237 | VR::UC
238 | VR::UI
239 | VR::UR
240 | VR::TM
241 | VR::ST
242 | VR::UT => {
243 serializer.serialize_entry("Value", &AsStrings::from(v))?;
244 }
245 VR::PN => {
246 serializer.serialize_entry("Value", &AsPersonNames::from(v))?;
247 }
248 VR::FD
249 | VR::IS
250 | VR::FL
251 | VR::DS
252 | VR::SL
253 | VR::SS
254 | VR::SV
255 | VR::UL
256 | VR::US
257 | VR::UV => {
258 serializer.serialize_entry("Value", &AsNumbers::from(v))?;
259 }
260 VR::OB | VR::OD | VR::OF | VR::OL | VR::OV | VR::OW | VR::UN => {
261 serializer.serialize_entry("InlineBinary", &InlineBinary::from(v))?;
262 }
263 VR::SQ => unreachable!("unexpected VR SQ in primitive value"),
264 },
265 }
266
267 serializer.end()
268 }
269}
270
271impl<D> From<InMemElement<D>> for DicomJson<InMemElement<D>> {
272 fn from(value: InMemElement<D>) -> Self {
273 Self(value)
274 }
275}
276
277impl<D> Serialize for DicomJson<InMemElement<D>> {
278 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
279 where
280 S: Serializer,
281 {
282 DicomJson(&self.0).serialize(serializer)
283 }
284}
285
286impl Serialize for DicomJson<&PixelFragmentSequence<Vec<u8>>> {
287 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
288 where
289 S: Serializer,
290 {
291 let offset_table = self.inner().offset_table();
292 let fragments = self.inner().fragments();
293 let mut map = serializer.serialize_map(Some(2))?;
294 map.serialize_entry("Offset Table", offset_table)?;
295 map.serialize_entry("Pixel Fragments", fragments)?;
296 map.end()
297 }
298}
299
300impl From<Tag> for DicomJson<Tag> {
301 fn from(value: Tag) -> Self {
302 Self(value)
303 }
304}
305
306impl Serialize for DicomJson<Tag> {
307 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
310 where
311 S: Serializer,
312 {
313 let Tag(g, e) = self.0;
314 serializer.serialize_str(&format!("{g:04X}{e:04X}"))
315 }
316}
317
318#[cfg(test)]
319mod tests {
320 use pretty_assertions::assert_eq;
321
322 use dicom_core::value::DataSetSequence;
323 use dicom_core::Length;
324 use dicom_core::{dicom_value, value::DicomDate};
325 use dicom_dictionary_std::tags;
326 use serde_json::json;
327
328 use super::*;
329
330 #[test]
331 fn serialize_simple_data_elements() {
332 let all_data = vec![
333 InMemElement::new(
334 Tag(0x0008, 0x0005),
335 VR::CS,
336 PrimitiveValue::from("ISO_IR 192"),
337 ),
338 InMemElement::new(
339 Tag(0x0008, 0x0020),
340 VR::DA,
341 PrimitiveValue::from(DicomDate::from_ymd(2013, 4, 9).unwrap()),
342 ),
343 InMemElement::new(
344 Tag(0x0008, 0x0061),
345 VR::CS,
346 dicom_value!(Strs, ["CT", "PET"]),
347 ),
348 InMemElement::new(
349 Tag(0x0008, 0x0090),
350 VR::PN,
351 PrimitiveValue::from("^Bob^^Dr."),
352 ),
353 InMemElement::new(
354 Tag(0x0009, 0x1002),
355 VR::UN,
356 dicom_value!(U8, [0xcf, 0x4c, 0x7d, 0x73, 0xcb, 0xfb]),
357 ),
358 InMemElement::new(tags::PATIENT_AGE, VR::AS, PrimitiveValue::from("30Y")),
359 ];
360
361 let obj = InMemDicomObject::from_element_iter(all_data);
362
363 assert_eq!(
364 to_value(&obj).unwrap(),
365 json!({
366 "00080005": {
367 "vr": "CS",
368 "Value": [ "ISO_IR 192" ]
369 },
370 "00080020": {
371 "vr": "DA",
372 "Value": [ "20130409" ]
373 },
374 "00080061": {
375 "vr": "CS",
376 "Value": [
377 "CT",
378 "PET"
379 ]
380 },
381 "00080090": {
382 "vr": "PN",
383 "Value": [
384 {
385 "Alphabetic": "^Bob^^Dr."
386 }
387 ]
388 },
389 "00091002": {
390 "vr": "UN",
391 "InlineBinary": "z0x9c8v7"
392 },
393 "00101010": {
394 "vr": "AS",
395 "Value": [ "30Y" ]
396 }
397 }),
398 );
399 }
400
401 #[test]
402 fn serialize_sequence_elements() {
403 let obj = InMemDicomObject::from_element_iter([InMemElement::new(
404 tags::SHARED_FUNCTIONAL_GROUPS_SEQUENCE,
405 VR::SQ,
406 DataSetSequence::new(
407 vec![
408 InMemDicomObject::from_element_iter([InMemElement::new(
410 tags::CT_ACQUISITION_TYPE_SEQUENCE,
411 VR::SQ,
412 DataSetSequence::new(
413 vec![
414 InMemDicomObject::from_element_iter([
416 InMemElement::new(
417 tags::ACQUISITION_TYPE,
418 VR::CS,
419 PrimitiveValue::from("SEQUENCED"),
420 ),
421 InMemElement::new(
422 tags::CONSTANT_VOLUME_FLAG,
423 VR::CS,
424 PrimitiveValue::from("NO"),
425 ),
426 InMemElement::new(
427 tags::FLUOROSCOPY_FLAG,
428 VR::CS,
429 PrimitiveValue::from("NO"),
430 ),
431 ]),
432 ],
433 Length::UNDEFINED,
434 ),
435 )]),
436 InMemDicomObject::from_element_iter([InMemElement::new(
438 tags::CT_ACQUISITION_DETAILS_SEQUENCE,
439 VR::SQ,
440 DataSetSequence::new(
441 vec![InMemDicomObject::from_element_iter([
442 InMemElement::new(
443 tags::DATA_COLLECTION_DIAMETER,
444 VR::DS,
445 PrimitiveValue::from("500.08"),
446 ),
447 InMemElement::new(
448 tags::GANTRY_DETECTOR_TILT,
449 VR::DS,
450 PrimitiveValue::from("0.00"),
451 ),
452 InMemElement::new(
453 tags::TABLE_HEIGHT,
454 VR::DS,
455 PrimitiveValue::from("160.000"),
456 ),
457 InMemElement::new(
458 tags::ROTATION_DIRECTION,
459 VR::CS,
460 PrimitiveValue::from("CW"),
461 ),
462 ])],
463 Length::UNDEFINED,
464 ),
465 )]),
466 ],
467 Length::UNDEFINED,
468 ),
469 )]);
470
471 assert_eq!(
472 to_value(obj).unwrap(),
473 json!({
474 "52009229": {
476 "vr": "SQ",
477 "Value": [
478 {
480 "00189301": {
481 "vr": "SQ",
482 "Value": [
483 {
484 "00189302": {
485 "vr": "CS",
486 "Value": ["SEQUENCED"]
487 },
488 "00189333": {
489 "vr": "CS",
490 "Value": ["NO"]
491 },
492 "00189334": {
493 "vr": "CS",
494 "Value": ["NO"]
495 }
496 }
497 ]
498 }
499 },
500 {
502 "00189304": {
503 "vr": "SQ",
504 "Value": [
505 {
506 "00180090": {
507 "vr": "DS",
508 "Value": ["500.08"]
509 },
510 "00181120": {
511 "vr": "DS",
512 "Value": ["0.00"]
513 },
514 "00181130": {
515 "vr": "DS",
516 "Value": ["160.000"]
517 },
518 "00181140": {
519 "vr": "CS",
520 "Value": ["CW"]
521 },
522 }
523 ]
524 }
525 }
526 ]
527 }
528 }),
529 );
530 }
531
532 #[test]
533 fn write_full_file_to_json() {
534 let sc_rgb_rle = dicom_test_files::path("pydicom/SC_rgb_rle.dcm").unwrap();
535
536 let obj = dicom_object::OpenFileOptions::new()
537 .read_until(Tag(0x0010, 0))
538 .open_file(sc_rgb_rle)
539 .expect("Failed to open test file");
540
541 let value = serde_json::to_value(DicomJson::from(obj)).unwrap();
542
543 assert_eq!(
544 value,
545 json!({
546 "00020000": {
547 "vr": "UL",
548 "Value": [238]
549 },
550 "00020001": {
551 "vr": "OB",
552 "InlineBinary": "AAE="
553 },
554 "00020002": {
555 "vr": "UI",
556 "Value": ["1.2.840.10008.5.1.4.1.1.7"]
557 },
558 "00020003": {
559 "vr": "UI",
560 "Value": ["1.2.826.0.1.3680043.8.498.49043964482360854182530167603505525116"]
561 },
562 "00020010": {
563 "vr": "UI",
564 "Value": ["1.2.840.10008.1.2.5"]
565 },
566 "00020012": {
567 "vr": "UI",
568 "Value": ["1.2.826.0.1.3680043.2.1143.107.104.103.115.2.8.4"]
569 },
570 "00020013": {
571 "vr": "SH",
572 "Value": ["GDCM 2.8.4"]
573 },
574 "00020016": {
575 "vr": "AE",
576 "Value": ["gdcmconv"]
577 },
578 "00080005": {
579 "vr": "CS",
580 "Value": ["ISO_IR 192"]
581 },
582 "00080008": {
583 "vr": "CS",
584 "Value": ["DERIVED", "SECONDARY", "OTHER"]
585 },
586 "00080016": {
587 "vr": "UI",
588 "Value": ["1.2.840.10008.5.1.4.1.1.7"]
589 },
590 "00080018": {
591 "vr": "UI",
592 "Value": ["1.2.826.0.1.3680043.8.498.49043964482360854182530167603505525116"]
593 },
594 "00080020": {
595 "vr": "DA",
596 "Value": ["20170101"]
597 },
598 "00080023": { "vr": "DA" },
599 "0008002A": { "vr": "DT" },
600 "00080030": {
601 "vr": "TM",
602 "Value": ["120000"],
603 },
604 "00080033": { "vr": "TM" },
605 "00080050": { "vr": "SH" },
606 "00080060": {
607 "vr": "CS",
608 "Value": ["OT"]
609 },
610 "00080064": {
611 "vr": "CS",
612 "Value": ["SYN"]
613 },
614 "00080090": {
615 "vr": "PN",
616 "Value": [
617 {
618 "Alphabetic": "Moriarty^James"
619 }
620 ]
621 }
622 })
623 );
624 }
625}