prost_reflect/dynamic/serde/mod.rs
1mod case;
2mod de;
3mod ser;
4
5use serde::{
6 de::{DeserializeSeed, Deserializer},
7 ser::{Serialize, Serializer},
8};
9
10use crate::{DynamicMessage, MessageDescriptor};
11
12/// Options to control serialization of messages.
13///
14/// Used by [`DynamicMessage::serialize_with_options()`].
15#[derive(Debug, Clone)]
16#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
17pub struct SerializeOptions {
18 stringify_64_bit_integers: bool,
19 use_enum_numbers: bool,
20 use_proto_field_name: bool,
21 skip_default_fields: bool,
22}
23
24/// Options to control deserialization of messages.
25///
26/// Used by [`DynamicMessage::deserialize_with_options()`].
27#[derive(Debug, Clone)]
28#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
29pub struct DeserializeOptions {
30 deny_unknown_fields: bool,
31}
32
33#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
34impl Serialize for DynamicMessage {
35 /// Serialize this message into `serializer` using the [canonical JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json).
36 ///
37 /// # Examples
38 ///
39 /// ```
40 /// # use prost::Message;
41 /// # use prost_types::FileDescriptorSet;
42 /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value};
43 /// # use serde::Serialize;
44 /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap();
45 /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();
46 /// let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01".as_ref()).unwrap();
47 /// let mut serializer = serde_json::Serializer::new(vec![]);
48 /// dynamic_message.serialize(&mut serializer).unwrap();
49 /// assert_eq!(serializer.into_inner(), b"{\"foo\":150}");
50 /// ```
51 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52 where
53 S: Serializer,
54 {
55 self.serialize_with_options(serializer, &Default::default())
56 }
57}
58
59#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
60impl<'de> DeserializeSeed<'de> for MessageDescriptor {
61 type Value = DynamicMessage;
62
63 /// Deserialize a [`DynamicMessage`] from `deserializer` using the [canonical JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json).
64 ///
65 /// # Examples
66 ///
67 /// ```
68 /// # use prost::Message;
69 /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value};
70 /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap();
71 /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();
72 /// use serde::de::DeserializeSeed;
73 ///
74 /// let json = r#"{ "foo": 150 }"#;
75 /// let mut deserializer = serde_json::de::Deserializer::from_str(json);
76 /// let dynamic_message = message_descriptor.deserialize(&mut deserializer).unwrap();
77 /// deserializer.end().unwrap();
78 ///
79 /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150));
80 /// ```
81 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
82 where
83 D: Deserializer<'de>,
84 {
85 DynamicMessage::deserialize(self, deserializer)
86 }
87}
88
89impl DynamicMessage {
90 /// Serialize this message into `serializer` using the encoding specified by `options`.
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// # use prost::Message;
96 /// # use prost_types::FileDescriptorSet;
97 /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, SerializeOptions};
98 /// # use serde::Serialize;
99 /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap();
100 /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();
101 /// let dynamic_message = DynamicMessage::new(message_descriptor);
102 /// let mut serializer = serde_json::Serializer::new(vec![]);
103 /// let mut options = SerializeOptions::new().skip_default_fields(false);
104 /// dynamic_message.serialize_with_options(&mut serializer, &options).unwrap();
105 /// assert_eq!(serializer.into_inner(), b"{\"foo\":0}");
106 /// ```
107 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
108 pub fn serialize_with_options<S>(
109 &self,
110 serializer: S,
111 options: &SerializeOptions,
112 ) -> Result<S::Ok, S::Error>
113 where
114 S: Serializer,
115 {
116 ser::serialize_message(self, serializer, options)
117 }
118
119 /// Deserialize an instance of the message type described by `desc` from `deserializer`.
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// # use prost::Message;
125 /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value};
126 /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap();
127 /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();
128 /// let json = r#"{ "foo": 150 }"#;
129 /// let mut deserializer = serde_json::de::Deserializer::from_str(json);
130 /// let dynamic_message = DynamicMessage::deserialize(message_descriptor, &mut deserializer).unwrap();
131 /// deserializer.end().unwrap();
132 ///
133 /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150));
134 /// ```
135 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
136 pub fn deserialize<'de, D>(desc: MessageDescriptor, deserializer: D) -> Result<Self, D::Error>
137 where
138 D: Deserializer<'de>,
139 {
140 Self::deserialize_with_options(desc, deserializer, &Default::default())
141 }
142
143 /// Deserialize an instance of the message type described by `desc` from `deserializer`, using
144 /// the encoding specified by `options`.
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// # use prost::Message;
150 /// # use prost_reflect::{DynamicMessage, DescriptorPool, Value, DeserializeOptions};
151 /// # let pool = DescriptorPool::decode(include_bytes!("../../file_descriptor_set.bin").as_ref()).unwrap();
152 /// # let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();
153 /// let json = r#"{ "foo": 150, "unknown": true }"#;
154 /// let mut deserializer = serde_json::de::Deserializer::from_str(json);
155 /// let options = DeserializeOptions::new().deny_unknown_fields(false);
156 /// let dynamic_message = DynamicMessage::deserialize_with_options(message_descriptor, &mut deserializer, &options).unwrap();
157 /// deserializer.end().unwrap();
158 ///
159 /// assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150));
160 /// ```
161 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
162 pub fn deserialize_with_options<'de, D>(
163 desc: MessageDescriptor,
164 deserializer: D,
165 options: &DeserializeOptions,
166 ) -> Result<Self, D::Error>
167 where
168 D: Deserializer<'de>,
169 {
170 de::deserialize_message(&desc, deserializer, options)
171 }
172}
173
174impl DeserializeOptions {
175 /// Creates a new instance of [`DeserializeOptions`], with the default options chosen to conform to
176 /// the standard JSON mapping.
177 pub const fn new() -> Self {
178 DeserializeOptions {
179 deny_unknown_fields: true,
180 }
181 }
182
183 /// Whether to error during deserialization when encountering unknown message fields.
184 ///
185 /// The default value is `true`.
186 pub const fn deny_unknown_fields(mut self, yes: bool) -> Self {
187 self.deny_unknown_fields = yes;
188 self
189 }
190}
191
192impl Default for DeserializeOptions {
193 fn default() -> Self {
194 Self::new()
195 }
196}
197
198impl SerializeOptions {
199 /// Creates a new instance of [`SerializeOptions`], with the default options chosen to conform to
200 /// the standard JSON mapping.
201 pub const fn new() -> Self {
202 SerializeOptions {
203 stringify_64_bit_integers: true,
204 use_enum_numbers: false,
205 use_proto_field_name: false,
206 skip_default_fields: true,
207 }
208 }
209
210 /// Whether to encode 64-bit integral types as strings.
211 ///
212 /// The spec requires encoding 64-bit integers as strings, to prevent loss of precision in JSON
213 /// when the value cannot be represented exactly by a double. If this option is disabled, all
214 /// numbers will be serialized as their corresponding serde types instead.
215 ///
216 /// The default value is `true`.
217 pub const fn stringify_64_bit_integers(mut self, yes: bool) -> Self {
218 self.stringify_64_bit_integers = yes;
219 self
220 }
221
222 /// Whether to encode enum values as their numeric value.
223 ///
224 /// If `true`, enum values will be serialized as their integer values. Otherwise, they will be
225 /// serialized as the string value specified in the proto file.
226 ///
227 /// The default value is `false`.
228 pub const fn use_enum_numbers(mut self, yes: bool) -> Self {
229 self.use_enum_numbers = yes;
230 self
231 }
232
233 /// Whether to use the proto field name instead of the lowerCamelCase name in JSON field names.
234 ///
235 /// The default value is `false`.
236 pub const fn use_proto_field_name(mut self, yes: bool) -> Self {
237 self.use_proto_field_name = yes;
238 self
239 }
240
241 /// Whether to skip fields which have their default value.
242 ///
243 /// If `true`, any fields for which [`has_field`][DynamicMessage::has_field] returns `false` will
244 /// not be serialized. If `false`, they will be serialized with their default value.
245 ///
246 /// The default value is `true`.
247 pub const fn skip_default_fields(mut self, yes: bool) -> Self {
248 self.skip_default_fields = yes;
249 self
250 }
251}
252
253impl Default for SerializeOptions {
254 fn default() -> Self {
255 Self::new()
256 }
257}
258
259const MAX_DURATION_SECONDS: u64 = 315_576_000_000;
260const MAX_DURATION_NANOS: u32 = 999_999_999;
261
262const MIN_TIMESTAMP_SECONDS: i64 = -62135596800;
263const MAX_TIMESTAMP_SECONDS: i64 = 253402300799;
264
265fn is_well_known_type(full_name: &str) -> bool {
266 matches!(
267 full_name,
268 "google.protobuf.Any"
269 | "google.protobuf.Timestamp"
270 | "google.protobuf.Duration"
271 | "google.protobuf.Struct"
272 | "google.protobuf.FloatValue"
273 | "google.protobuf.DoubleValue"
274 | "google.protobuf.Int32Value"
275 | "google.protobuf.Int64Value"
276 | "google.protobuf.UInt32Value"
277 | "google.protobuf.UInt64Value"
278 | "google.protobuf.BoolValue"
279 | "google.protobuf.StringValue"
280 | "google.protobuf.BytesValue"
281 | "google.protobuf.FieldMask"
282 | "google.protobuf.ListValue"
283 | "google.protobuf.Value"
284 | "google.protobuf.Empty"
285 )
286}
287
288fn check_duration(duration: &prost_types::Duration) -> Result<(), &'static str> {
289 if duration.seconds.unsigned_abs() > MAX_DURATION_SECONDS
290 || duration.nanos.unsigned_abs() > MAX_DURATION_NANOS
291 {
292 Err("duration out of range")
293 } else {
294 Ok(())
295 }
296}
297
298fn check_timestamp(timestamp: &prost_types::Timestamp) -> Result<(), &'static str> {
299 if timestamp.seconds < MIN_TIMESTAMP_SECONDS || MAX_TIMESTAMP_SECONDS < timestamp.seconds {
300 Err("timestamp out of range")
301 } else {
302 Ok(())
303 }
304}