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
Copy file name to clipboardExpand all lines: src/content/reference/rust/concepts/rust-after-3.0.mdx
+142-4Lines changed: 142 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -492,13 +492,35 @@ async fn main() {
492
492
493
493
## Enum and struct attributes
494
494
495
-
The `SurrealValue`trait can be customised using the `surreal` attribute. These are used in a similar way to [Serde attributes](https://serde.rs/attributes.html), though created in order to interact with SurrealQL in particular and thus often somewhat different.
495
+
The `SurrealValue`derive uses its own `#[surreal(...)]` attribute that is inspired by [Serde](https://serde.rs/attributes.html) (familiar names, similar enum tagging ideas), but it is **not** Serde and not an inheritance of `#[serde(...)]` attributes.
496
496
497
-
The currently available attributes are as follows.
497
+
In SurrealDB 2.x, many SDK types used Serde’s `Serialize` / `Deserialize` derives. In 3.0, conversion goes through `SurrealValue` and a dedicated derive macro. If you previously reached for Serde docs to customise field names or flattening, use the matching `#[surreal(...)]` form below instead.
498
+
499
+
### Relationship to Serde
500
+
501
+
| Idea | Serde |`SurrealValue` (`#[surreal(...)]`) |
502
+
| --- | --- | --- |
503
+
| Rename one field / variant |`rename = "..."`|`rename = "..."`|
504
+
| Rename all fields / variants |`rename_all = "..."`|`rename_all = "..."` (same case strings as Serde) |
| Missing field default |`default` / `default = "path"`|`default` / `default = "path"` (also on the container) |
508
+
| Catch-all unit variant |`other`|`other`|
509
+
| Skip a field |`skip`, `skip_serializing`, `skip_serializing_if`| Not supported on ordinary fields |
510
+
| Conditionally omit enum payload | (use field `skip_serializing_if`) |`skip_content` / `skip_content_if = "..."` on tagged enums |
511
+
| Serde-only types | (n/a) |`wrap` for `Serialize + Deserialize` types that do not implement `SurrealValue`|
512
+
| Tuple struct as array | (n/a) |`tuple`|
513
+
| Literal substitute for a unit | (n/a) |`value = ...`|
514
+
515
+
Supported `rename_all` values match Serde’s usual set (`lowercase`, `UPPERCASE`, `PascalCase`, `camelCase`, `snake_case`, `SCREAMING_SNAKE_CASE`, `kebab-case`, `SCREAMING-KEBAB-CASE`). An explicit `rename` on a field or variant wins over the container `rename_all`.
516
+
517
+
`#[surreal(uppercase)]` and `#[surreal(lowercase)]` on enums are legacy aliases for `rename_all = "UPPERCASE"` and `rename_all = "lowercase"`. Prefer `rename_all` in new code. Do not combine them with `rename_all` on the same enum.
518
+
519
+
The attributes below are the ones the derive currently recognises.
498
520
499
521
### `surreal(default)`
500
522
501
-
The `surreal(default)` attribute is used to default to certain values when these values are not present when deserializing. The `Default`trait is required to use this.
523
+
The `surreal(default)` attribute fills in values when fields are missing during deserialization. On a struct container, missing fields come from the type’s `Default`implementation. On a single field, use `#[surreal(default)]` for `<T as Default>::default()`, or `#[surreal(default = "path")]` for a custom function path.
502
524
503
525
```rust
504
526
usesurrealdb::engine::any::connect;
@@ -597,9 +619,65 @@ Before rename: { num: 555 }
597
619
After rename: { user_num: 555 }
598
620
```
599
621
622
+
### `surreal(rename_all)`
623
+
624
+
Apply a case transform to every field name on a struct, or every variant name on an enum, unless a field or variant sets its own `rename`.
625
+
626
+
```rust
627
+
usesurrealdb_types::{SurrealValue, ToSql};
628
+
629
+
#[derive(SurrealValue)]
630
+
#[surreal(rename_all ="camelCase")]
631
+
structUserProfile {
632
+
full_name:String,
633
+
years_old:i64,
634
+
}
635
+
636
+
fnmain() {
637
+
letprofile=UserProfile {
638
+
full_name:"Ada".into(),
639
+
years_old:36,
640
+
};
641
+
// { fullName: 'Ada', yearsOld: 36 }
642
+
println!("{}", profile.into_value().to_sql());
643
+
}
644
+
```
645
+
646
+
### `surreal(flatten)`
647
+
648
+
Merge a nested object’s fields into the parent object instead of nesting them under one key. This is the Surreal equivalent of Serde’s `#[serde(flatten)]`.
649
+
650
+
```rust
651
+
usesurrealdb_types::{SurrealValue, ToSql};
652
+
653
+
#[derive(SurrealValue)]
654
+
structCoords {
655
+
x:i64,
656
+
y:i64,
657
+
}
658
+
659
+
#[derive(SurrealValue)]
660
+
structPoint {
661
+
name:String,
662
+
#[surreal(flatten)]
663
+
coords:Coords,
664
+
}
665
+
666
+
fnmain() {
667
+
letpoint=Point {
668
+
name:"origin".into(),
669
+
coords:Coords { x:0, y:0 },
670
+
};
671
+
// { name: 'origin', x: 0, y: 0 }
672
+
println!("{}", point.into_value().to_sql());
673
+
}
674
+
```
675
+
676
+
`flatten` cannot be combined with `rename` on the same field: there is no single key left to rename.
677
+
600
678
### `surreal(uppercase)` and `surreal(lowercase)`
601
679
602
-
These two attributes are similar to `surreal(rename)` except that they apply to the casing of enum variants.
680
+
These two attributes are legacy aliases for `rename_all = "UPPERCASE"` and `rename_all = "lowercase"` on enums. Prefer `rename_all` when writing new types.
603
681
604
682
```rust
605
683
usesurrealdb_types::{SurrealValue, ToSql};
@@ -779,6 +857,66 @@ Before content: { Debug: 'User1' }
779
857
After content: { log_level: 'Debug', user: 'User1' }
780
858
```
781
859
860
+
### `surreal(skip_content)` and `surreal(skip_content_if)`
861
+
862
+
On enums that use adjacent tagging (`tag` plus `content`), these control whether the content field is written (and whether it may be absent when reading).
863
+
864
+
They are the closest Surreal analogues to Serde’s `skip_serializing_if`, but they apply to the enum content field, not to arbitrary struct fields.
865
+
866
+
| Attribute | Effect |
867
+
| --- | --- |
868
+
|`skip_content`| Never emit the content field for that enum or variant |
869
+
|`skip_content_if = "path"`| Emit content only when the predicate returns false (for example `Value::is_empty`) |
You can also put `skip_content` or `skip_content_if` on individual variants. They only apply to enums that already declare a `tag` (with or without `content`).
900
+
901
+
### `surreal(other)`
902
+
903
+
On a **unit** variant, `other` marks a deserialization catch-all: if no other variant matches, that variant is chosen instead of returning an error. At most one variant per enum should use it. It cannot be combined with `rename` or `value` on the same variant.
904
+
905
+
```rust
906
+
usesurrealdb_types::SurrealValue;
907
+
908
+
#[derive(Debug, PartialEq, SurrealValue)]
909
+
#[surreal(untagged)]
910
+
enumWireFlag {
911
+
#[surreal(value = true)]
912
+
On,
913
+
#[surreal(value = false)]
914
+
Off,
915
+
#[surreal(other)]
916
+
Unknown,
917
+
}
918
+
```
919
+
782
920
### `surreal(value)`
783
921
784
922
This attribute can be used on the fields of an enum marked with `surreal(untagged)` to give it a substitute value. The value that follows this attribute can be a NONE, NULL, bool, string, int, or float.
0 commit comments