Skip to content
This repository has been archived by the owner on Jul 9, 2023. It is now read-only.

Attribute macro to skip serializing all fields of Option type #18

Closed
dtolnay opened this issue Jan 22, 2019 · 4 comments · Fixed by #31
Closed

Attribute macro to skip serializing all fields of Option type #18

dtolnay opened this issue Jan 22, 2019 · 4 comments · Fixed by #31

Comments

@dtolnay
Copy link
Owner

dtolnay commented Jan 22, 2019

Some JSON workflows involve practically every piece of data being nullable and none of then being serialized when null. The Serde attributes in this situation can be verbose and distracting.

#[derive(Serialize)]
struct Data {
    id: u64,
    #[serde(skip_serializing_if = "Option::is_none")]
    a: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    b: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    c: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    d: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    e: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    f: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    g: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    h: Option<String>,
}

It would be better to have an attribute macro that finds all fields of type Option<_> and inserts a skip_serializing_if attribute.

#[skip_serializing_null]
#[derive(Serialize)]
struct Data {
    id: u64,
    a: Option<String>,
    b: Option<String>,
    c: Option<String>,
    d: Option<String>,
    e: Option<String>,
    f: Option<String>,
    g: Option<String>,
    h: Option<String>,
}

Optionally consider supporting an attribute to annotate optional fields that always need to be serialized, even when null.

#[skip_serializing_null]
#[derive(Serialize)]
struct Data {
    id: u64,
    #[always]
    a: Option<String>,
    b: Option<String>,
    /* ... */
}
jonasbb added a commit to jonasbb/serde_with that referenced this issue Mar 19, 2019
A proc_macro is required to implement skip_serializing_null from
dtolnay/request-for-implementation#18
@jonasbb
Copy link

jonasbb commented Mar 19, 2019

I'm tackling this issue over at jonasbb/serde_with#46

EDIT: This feature is included in version 1.3.0 of serde_with.

jonasbb added a commit to jonasbb/serde_with that referenced this issue Mar 31, 2019
A proc_macro is required to implement skip_serializing_null from
dtolnay/request-for-implementation#18

Expose the macro crate in serde_with

* Add a "macros"-feature to disable compiling proc_macros
* Add the feature to the testing matrix
bors bot added a commit to jonasbb/serde_with that referenced this issue Mar 31, 2019
46: Add a `skip_serializing_null` attribute r=jonasbb a=jonasbb

The `skip_serializing_null` attribute can be added to any struct and adds `#[serde(skip_serializing_if = "Option::is_none")]` to every `Option` field.
The intended use is for parsing data, e.g., from APIs, which has many optional values.

It turns

```rust
#[skip_serializing_null]
#[derive(Serialize)]
struct Data {
    a: Option<String>,
    b: Option<String>,
    c: Option<String>,
    d: Option<String>,
}
```

into

```rust
#[derive(Serialize)]
struct Data {
    #[serde(skip_serializing_if = "Option::is_none")]
    a: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    b: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    c: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    d: Option<String>,
}
```

The issue was originally suggested at dtolnay/request-for-implementation#18.

# Missing

* [x] Is `skip_serializing_null` the best name? That is how serde or JSON name the empty value, in Rust it is none.
* [x] Support tuple structs
* [x] Support enums
* [x] Handle existing `skip_serializing_if` annotations, by skipping those fields
* [x] Support an additional attribute, which ensures the field is always serialized
* [x] Write compile tests, which ensure the correct error message
* [x] Write documentation for the feature

Co-authored-by: Jonas Bushart <[email protected]>
bors bot added a commit to jonasbb/serde_with that referenced this issue Apr 2, 2019
46: Add a `skip_serializing_null` attribute r=jonasbb a=jonasbb

The `skip_serializing_null` attribute can be added to any struct and adds `#[serde(skip_serializing_if = "Option::is_none")]` to every `Option` field.
The intended use is for parsing data, e.g., from APIs, which has many optional values.

It turns

```rust
#[skip_serializing_null]
#[derive(Serialize)]
struct Data {
    a: Option<String>,
    b: Option<String>,
    c: Option<String>,
    d: Option<String>,
}
```

into

```rust
#[derive(Serialize)]
struct Data {
    #[serde(skip_serializing_if = "Option::is_none")]
    a: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    b: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    c: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    d: Option<String>,
}
```

The issue was originally suggested at dtolnay/request-for-implementation#18.

# Missing

* [x] Is `skip_serializing_null` the best name? That is how serde or JSON name the empty value, in Rust it is none.
* [x] Support tuple structs
* [x] Support enums
* [x] Handle existing `skip_serializing_if` annotations, by skipping those fields
* [x] Support an additional attribute, which ensures the field is always serialized
* [x] Write compile tests, which ensure the correct error message
* [x] Write documentation for the feature

Co-authored-by: Jonas Bushart <[email protected]>
@jonathan-s
Copy link
Contributor

Looks like this feature is completed, no?

@Warfields
Copy link

???

@DrSensor
Copy link

I think this already shipped in the current crate serde_with. I've used it and it works as expected. The only thing missing is the documentation 🤔

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants