dicom_json/
lib.rs

1#![warn(missing_docs)]
2//! DICOM JSON module
3//!
4//!
5//! This library provides serialization of DICOM data to JSON
6//! and deserialization of JSON to DICOM data,
7//! as per the [DICOM standard part 18 chapter F][1].
8//!
9//! [1]: https://dicom.nema.org/medical/dicom/current/output/chtml/part18/chapter_F.html
10//!
11//! The easiest path to serialization is in
12//! using the functions readily available [`to_string`] and [`to_value`].
13//! Alternatively, DICOM data can be enclosed by a [`DicomJson`] value,
14//! which implements serialization and deserialization via [Serde](serde).
15//!
16//! # Example
17//!
18//! To serialize an object to standard DICOM JSON:
19//!
20//! ```
21//! # use dicom_core::{PrimitiveValue, VR};
22//! # use dicom_object::mem::{InMemDicomObject, InMemElement};
23//! # use dicom_dictionary_std::tags;
24//! let obj = InMemDicomObject::from_element_iter([
25//!     InMemElement::new(tags::SERIES_DATE, VR::DA, "20230610"),
26//!     InMemElement::new(tags::INSTANCE_NUMBER, VR::IS, "5"),
27//! ]);
28//!
29//! let json = dicom_json::to_string(&obj)?;
30//!
31//! assert_eq!(
32//!     json,
33//!     r#"{"00080021":{"vr":"DA","Value":["20230610"]},"00200013":{"vr":"IS","Value":["5"]}}"#
34//! );
35//! # Ok::<(), serde_json::Error>(())
36//! ```
37//!
38//! To turn DICOM JSON back into an in-memory object:
39//!
40//! ```
41//! # use dicom_object::mem::InMemDicomObject;
42//! let json = r#"{
43//!     "00080021": { "vr": "DA", "Value":["20230610"] },
44//!     "00200013": { "vr": "IS", "Value":["5"] }
45//! }"#;
46//! let obj: InMemDicomObject = dicom_json::from_str(&json)?;
47//! # Ok::<(), serde_json::Error>(())
48//! ```
49//!
50//! Use the [`DicomJson`] wrapper type
51//! for greater control on how to serialize or deserialize data:
52//!
53//! ```rust
54//! # use dicom_core::{PrimitiveValue, VR};
55//! # use dicom_object::mem::{InMemDicomObject, InMemElement};
56//! # use dicom_dictionary_std::tags;
57//! # let obj = InMemDicomObject::from_element_iter([
58//! #     InMemElement::new(tags::SERIES_DATE, VR::DA, "20230610"),
59//! #     InMemElement::new(tags::INSTANCE_NUMBER, VR::IS, "5"),
60//! # ]);
61//! let dicom_obj = dicom_json::DicomJson::from(&obj);
62//! let serialized = serde_json::to_value(dicom_obj)?;
63//!
64//! assert_eq!(
65//!     serialized,
66//!     serde_json::json!({
67//!         "00080021": {
68//!             "vr": "DA",
69//!             "Value": [ "20230610" ]
70//!         },
71//!         "00200013": {
72//!             "vr": "IS",
73//!             "Value": [ "5" ]
74//!         }
75//!     }),
76//! );
77//! # Ok::<(), serde_json::Error>(())
78//! ```
79
80mod de;
81mod ser;
82
83pub use crate::de::{from_reader, from_slice, from_str, from_value};
84pub use crate::ser::{to_string, to_string_pretty, to_value, to_vec, to_writer};
85
86/// Represents the serialized representation of "NaN" (Not a Number) for 32-bit float (FL) and 64-bit float (FD) in DICOM JSON.
87pub const NAN: &str = "NaN";
88/// Represents the serialized representation of "inf" (positive infinity) for 32-bit float (FL) and 64-bit float (FD) in DICOM JSON.
89pub const INFINITY: &str = "inf";
90/// Represents the serialized representation of "-inf" (negative infinity) for 32-bit float (FL) and 64-bit float (FD) in DICOM JSON.
91pub const NEG_INFINITY: &str = "-inf";
92
93/// A wrapper type for DICOM JSON serialization using [Serde](serde).
94///
95/// Serializing this type will yield JSON data according to the standard.
96/// Deserialization from this type
97/// will interpret the input data as standard DICOM JSON deserialization.
98///
99/// # Serialization
100///
101/// Convert a DICOM data type such as a file, object, or data element
102/// into a `DicomJson` value using [`From`] or [`Into`],
103/// then use a JSON serializer such as the one in [`serde_json`]
104/// to serialize it to the intended type.
105/// A reference may be used as well,
106/// so as to not consume the DICOM data.
107///
108/// `DicomJson` can serialize:
109///
110/// - [`InMemDicomObject`][1] as a standard DICOM JSON data set;
111/// - [`InMemElement`][2] by writing the VR and value in a single object
112///   (note that the tag will not be serialized);
113/// - `&[InMemDicomObject]` and `Vec<InMemDicomObject>`,
114///   resulting in a JSON array of DICOM JSON data sets;
115/// - [`DefaultDicomObject`][3],
116///   which will also include the attributes from the file meta group.
117///   Note however, that this is not conforming to the standard.
118///   Obtain the inner data set through [`Deref`][4] (`&*obj`)
119///   if you do not wish to include file meta group data.
120/// - [`Tag`][5]: values are written as a single string
121///   in the expected DICOM JSON format `"GGGGEEEE"`
122///   where `GGGG` and `EEEE` are the group/element parts
123///   in uppercase hexadecimal.
124///
125/// [1]: dicom_object::InMemDicomObject
126/// [2]: dicom_object::mem::InMemElement
127/// [3]: dicom_object::DefaultDicomObject
128/// [4]: std::ops::Deref
129/// [5]: dicom_core::Tag
130///
131/// ## Example
132///
133/// ```
134/// # use dicom_core::{DataElement, PrimitiveValue, Tag, VR};
135/// # use dicom_object::InMemDicomObject;
136/// use dicom_json::DicomJson;
137///
138/// // creating a DICOM object with a single attribute
139/// let obj = InMemDicomObject::from_element_iter([
140///     DataElement::new(
141///         Tag(0x0010, 0x0020),
142///         VR::LO,
143///         PrimitiveValue::from("ID0001"),
144///     )
145/// ]);
146/// // wrap it with DicomJson
147/// let json_obj = DicomJson::from(&obj);
148/// // serialize it to a JSON Value
149/// let serialized = serde_json::to_value(&json_obj)?;
150/// assert_eq!(
151///   serialized,
152///   serde_json::json!({
153///       "00100020": {
154///           "vr": "LO",
155///           "Value": [ "ID0001" ]
156///       }
157///   })
158/// );
159/// # Result::<_, serde_json::Error>::Ok(())
160/// ```
161///
162/// # Deserialization
163///
164/// Specify the concrete DICOM data type to deserialize to,
165/// place it as the type parameter `T` of `DicomJson<T>`,
166/// then request to deserialize it.
167///
168/// `DicomJson` can deserialize:
169///
170/// - [`InMemDicomObject`][1], expecting a JSON object indexed by tags;
171/// - [`Tag`][5], a string formatted as a DICOM tag;
172/// - [`VR`][6], a 2-character string with one of the supported
173///   value representation identifiers.
174///
175/// [6]: dicom_core::VR
176///
177/// ## Example
178///
179/// ```
180/// # use dicom_core::{DataElement, PrimitiveValue, Tag, VR};
181/// # use dicom_object::InMemDicomObject;
182/// use dicom_json::DicomJson;
183///
184/// // given this JSON data
185/// let json_data = r#"{
186///     "00100020": {
187///         "vr": "LO",
188///         "Value": [ "ID0001" ]
189///     }
190/// }"#;
191/// // deserialize to DicomJson, then unwrap it
192/// let deserialized: DicomJson<InMemDicomObject> = serde_json::from_str(json_data)?;
193/// let obj = deserialized.into_inner();
194/// assert_eq!(
195///   obj,
196///   InMemDicomObject::from_element_iter([
197///       DataElement::new(Tag(0x0010, 0x0020), VR::LO, "ID0001"),
198///   ]),
199/// );
200/// # Ok::<(), serde_json::Error>(())
201/// ```
202#[derive(Debug, Clone, PartialEq)]
203pub struct DicomJson<T>(T);
204
205impl<T> DicomJson<T> {
206    /// Unwrap the DICOM JSON wrapper,
207    /// returning the underlying value.
208    pub fn into_inner(self) -> T {
209        self.0
210    }
211
212    /// Obtain a reference to the underlying value.
213    pub fn inner(&self) -> &T {
214        &self.0
215    }
216}