1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#![warn(missing_docs)]
//! DICOM JSON module
//!
//!
//! This library provides serialization of DICOM data to JSON
//! and deserialization of JSON to DICOM data,
//! as per the [DICOM standard part 18 chapter F][1].
//!
//! [1]: https://dicom.nema.org/medical/dicom/current/output/chtml/part18/chapter_F.html
//!
//! The easiest path to serialization is in
//! using the functions readily available [`to_string`] and [`to_value`].
//! Alternatively, DICOM data can be enclosed by a [`DicomJson`] value,
//! which implements serialization and deserialization via [Serde](serde).
//!
//! # Example
//!
//! To serialize an object to standard DICOM JSON:
//!
//! ```
//! # use dicom_core::{PrimitiveValue, VR};
//! # use dicom_object::mem::{InMemDicomObject, InMemElement};
//! # use dicom_dictionary_std::tags;
//! let obj = InMemDicomObject::from_element_iter([
//!     InMemElement::new(tags::SERIES_DATE, VR::DA, "20230610"),
//!     InMemElement::new(tags::INSTANCE_NUMBER, VR::IS, "5"),
//! ]);
//!
//! let json = dicom_json::to_string(&obj)?;
//!
//! assert_eq!(
//!     json,
//!     r#"{"00080021":{"vr":"DA","Value":["20230610"]},"00200013":{"vr":"IS","Value":["5"]}}"#
//! );
//! # Ok::<(), serde_json::Error>(())
//! ```
//!
//! To turn DICOM JSON back into an in-memory object:
//!
//! ```
//! # use dicom_object::mem::InMemDicomObject;
//! let json = r#"{
//!     "00080021": { "vr": "DA", "Value":["20230610"] },
//!     "00200013": { "vr": "IS", "Value":["5"] }
//! }"#;
//! let obj: InMemDicomObject = dicom_json::from_str(&json)?;
//! # Ok::<(), serde_json::Error>(())
//! ```
//!
//! Use the [`DicomJson`] wrapper type
//! for greater control on how to serialize or deserialize data:
//!
//! ```rust
//! # use dicom_core::{PrimitiveValue, VR};
//! # use dicom_object::mem::{InMemDicomObject, InMemElement};
//! # use dicom_dictionary_std::tags;
//! # let obj = InMemDicomObject::from_element_iter([
//! #     InMemElement::new(tags::SERIES_DATE, VR::DA, "20230610"),
//! #     InMemElement::new(tags::INSTANCE_NUMBER, VR::IS, "5"),
//! # ]);
//! let dicom_obj = dicom_json::DicomJson::from(&obj);
//! let serialized = serde_json::to_value(dicom_obj)?;
//!
//! assert_eq!(
//!     serialized,
//!     serde_json::json!({
//!         "00080021": {
//!             "vr": "DA",
//!             "Value": [ "20230610" ]
//!         },
//!         "00200013": {
//!             "vr": "IS",
//!             "Value": [ "5" ]
//!         }
//!     }),
//! );
//! # Ok::<(), serde_json::Error>(())
//! ```

mod de;
mod ser;

pub use crate::de::{from_reader, from_slice, from_str, from_value};
pub use crate::ser::{to_string, to_string_pretty, to_value, to_vec, to_writer};

/// A wrapper type for DICOM JSON serialization using [Serde](serde).
///
/// Serializing this type will yield JSON data according to the standard.
/// Deserialization from this type
/// will interpret the input data as standard DICOM JSON deserialization.
///
/// # Serialization
///
/// Convert a DICOM data type such as a file, object, or data element
/// into a `DicomJson` value using [`From`] or [`Into`],
/// then use a JSON serializer such as the one in [`serde_json`]
/// to serialize it to the intended type.
/// A reference may be used as well,
/// so as to not consume the DICOM data.
///
/// `DicomJson` can serialize:
///
/// - [`InMemDicomObject`][1] as a standard DICOM JSON data set;
/// - [`InMemElement`][2] by writing the VR and value in a single object
///   (note that the tag will not be serialized);
/// - `&[InMemDicomObject]` and `Vec<InMemDicomObject>`,
///   resulting in a JSON array of DICOM JSON data sets;
/// - [`DefaultDicomObject`][3],
///   which will also include the attributes from the file meta group.
///   Note however, that this is not conforming to the standard.
///   Obtain the inner data set through [`Deref`][4] (`&*obj`)
///   if you do not wish to include file meta group data.
/// - [`Tag`][5]: values are written as a single string
///   in the expected DICOM JSON format `"GGGGEEEE"`
///   where `GGGG` and `EEEE` are the group/element parts
///   in uppercase hexadecimal.
///
/// [1]: dicom_object::InMemDicomObject
/// [2]: dicom_object::mem::InMemElement
/// [3]: dicom_object::DefaultDicomObject
/// [4]: std::ops::Deref
/// [5]: dicom_core::Tag
///
/// ## Example
///
/// ```
/// # use dicom_core::{DataElement, PrimitiveValue, Tag, VR};
/// # use dicom_object::InMemDicomObject;
/// use dicom_json::DicomJson;
///
/// // creating a DICOM object with a single attribute
/// let obj = InMemDicomObject::from_element_iter([
///     DataElement::new(
///         Tag(0x0010, 0x0020),
///         VR::LO,
///         PrimitiveValue::from("ID0001"),
///     )
/// ]);
/// // wrap it with DicomJson
/// let json_obj = DicomJson::from(&obj);
/// // serialize it to a JSON Value
/// let serialized = serde_json::to_value(&json_obj)?;
/// assert_eq!(
///   serialized,
///   serde_json::json!({
///       "00100020": {
///           "vr": "LO",
///           "Value": [ "ID0001" ]
///       }
///   })
/// );
/// # Result::<_, serde_json::Error>::Ok(())
/// ```
///
/// # Deserialization
///
/// Specify the concrete DICOM data type to deserialize to,
/// place it as the type parameter `T` of `DicomJson<T>`,
/// then request to deserialize it.
///
/// `DicomJson` can deserialize:
///
/// - [`InMemDicomObject`][1], expecting a JSON object indexed by tags;
/// - [`Tag`][5], a string formatted as a DICOM tag;
/// - [`VR`][6], a 2-character string with one of the supported
///   value representation identifiers.
///
/// [6]: dicom_core::VR
///
/// ## Example
///
/// ```
/// # use dicom_core::{DataElement, PrimitiveValue, Tag, VR};
/// # use dicom_object::InMemDicomObject;
/// use dicom_json::DicomJson;
///
/// // given this JSON data
/// let json_data = r#"{
///     "00100020": {
///         "vr": "LO",
///         "Value": [ "ID0001" ]
///     }
/// }"#;
/// // deserialize to DicomJson, then unwrap it
/// let deserialized: DicomJson<InMemDicomObject> = serde_json::from_str(json_data)?;
/// let obj = deserialized.into_inner();
/// assert_eq!(
///   obj,
///   InMemDicomObject::from_element_iter([
///       DataElement::new(Tag(0x0010, 0x0020), VR::LO, "ID0001"),
///   ]),
/// );
/// # Ok::<(), serde_json::Error>(())
/// ```
#[derive(Debug, Clone, PartialEq)]
pub struct DicomJson<T>(T);

impl<T> DicomJson<T> {
    /// Unwrap the DICOM JSON wrapper,
    /// returning the underlying value.
    pub fn into_inner(self) -> T {
        self.0
    }

    /// Obtain a reference to the underlying value.
    pub fn inner(&self) -> &T {
        &self.0
    }
}