You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
with {:ok, shadow} <-Speck.validate(MQTT.AWS.Shadow.Update.V1, payload),
191
-
{:ok, light_state} <-Speck.validate(MQTT.Light.State.V1, shadow.state.desired) do
190
+
with {:ok, shadow, _meta} <-Speck.validate(MQTT.AWS.Shadow.Update.V1, payload),
191
+
{:ok, light_state, _meta} <-Speck.validate(MQTT.Light.State.V1, shadow.state.desired) do
192
192
# do something with light_state
193
193
end
194
194
```
@@ -234,3 +234,63 @@ name "add_device"
234
234
attribute :id, :integer, strict:true
235
235
attribute :name, :string
236
236
```
237
+
238
+
## Validation metadata
239
+
240
+
In certain situations, only having the coerced data may not be enough, and you may need information about the input data as well. Since Speck has already traversed the input data, information about it is collected and returned as validation metadata. Speck provides `Speck.ValidationMetadata.Attribute` for working with metadata attributes that describe the input data structure.
241
+
242
+
### Device shadows
243
+
244
+
One scenario where Speck's metadata is helpful is when working with a device shadow, like in AWS IoT Core. This shadow uses a `desired` property for sending data to an embedded device, and `reported` for the device to report its current state. When validating one of these messages with Speck, the schema will not know about new desired properties if they are added in the cloud before the firmware is updated. Unfortunately, AWS will continue to send delta updates until these new desired properties are acknowledged in the reported properties.
245
+
246
+
In this case, the metadata can be captured along with the validated message.
The new, unknown fields will be filtered out of `message` during the validation process, as expected. This message is trusted data that should still be sent down to the business logic layer for processing. However, the unknown fields need to be reported to the device shadow to acknowledge them. This is where `meta` comes in.
253
+
254
+
Using `meta`, the unknown fields can be selected with a filter, and they can be merged into the `reported` map to send to the shadow.
255
+
256
+
```elixir
257
+
reported = %{
258
+
# Real data to report to the shadow ...
259
+
}
260
+
261
+
meta
262
+
|>Attribute.list
263
+
|>Enum.filter(fn
264
+
{_path, :unknown, _value} ->true
265
+
{_path, _status, _value} ->false
266
+
end)
267
+
|>Attribute.merge(reported)
268
+
```
269
+
270
+
### Fields as actions
271
+
272
+
Although typically fields in protocols carry data, sometimes their presence or a `nil` value signifies an action to perform. For example, setting a field `nil` signifies a delete (remove/cleanup) should be performed, versus the field not being present meaning there is no change. Speck's coercion process intentionally obscures this, since the primary goal is to normalize the input into a consistent data structure. This is another situation where Speck's metadata can be used to determine which fields are marked for deletion.
0 commit comments