Serde: How to skip field with data type condition for JSON serialize & deserialize

Created on 14 Jun 2018  路  3Comments  路  Source: serde-rs/serde

I implement Rest API server return the payload with the format like that:

For success with status code 200.

{
    "statusCode": 200, 
    "message": "Ok",
    "data": {
        "name": "Peter",
        "age": 18
    }
}

And for error

{
    "statusCode": 500,
    "message": "Bad request",
    "error": "Your data is not correct"
}

In case I define I struct like that

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct HttpResponseData {
    name: String,
    age: u8,
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct HttpResponse<T> {
    status_code: i32,
    message: String,
    error: Option<String>,
    data: Option<T>,
}

So how to skip JSON field error or data base on condition or data type macro if I using serialize for struct appoarch?

let ok_resposne = Json(HttpResponse {
        status_code: 200,
        message: "Ok".to_string(),
        error: None, // How can skip this field, due it will be null value
        data: Some(HttpResponseData {
            name: name,
            age: age,
        }),
    });

let ok_resposne = Json(HttpResponse {
        status_code: 500,
        message: "BadRequest".to_string(),
        error: Some("Your data is not correct".to_string()),
        data: None, // How can skip this field, due it will be null value
    }) 
support

Most helpful comment

Check out this example which uses skip_serializing_if to conditionally skip fields. In your case that could be skip_serializing_if = "Option::is_none".

All 3 comments

Check out this example which uses skip_serializing_if to conditionally skip fields. In your case that could be skip_serializing_if = "Option::is_none".

@dtolnay In case the data or error field have 3 states

  • null
  • data
  • skip (undefined)

So how to solve this case? If I use JSON as payload for update data to the database like:

// Update with name, age, managerId
{
    "id": 123,
    "name": "Peter",
    "age": 17,
     "managerId": 12
}

// Update manager is null
{
    "id": 123,
    "name": "Peter",
    "age": 17,
     "managerId": null
}

// Update age & name only, other field skip
{
    "id": 123,
    "name": "Peter",
    "age": 17
}

In the case above, the managerId field can be null, skip, value.

You would need some data structure on the Rust side that can distinguish between the 3 states, i.e. Option<u64> is not sufficient for managerId because that could only represent null vs data, or skipped vs data.

Option<Option<u64>> could work, where None could mean skipped and Some(None) could mean null. https://github.com/serde-rs/serde/issues/984 has an example of how to set this up.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pitkley picture pitkley  路  3Comments

kleimkuhler picture kleimkuhler  路  3Comments

vityafx picture vityafx  路  3Comments

sackery picture sackery  路  3Comments

dtolnay picture dtolnay  路  4Comments