How to serialize struct in 3rd library with serde_json?

I want to call the api in aws-sdk-rust to get aws resources' parameter and serialize the result to json file. (for example, sdk/lambda/src/client/get_function.rs in aws-sdk-lambda)

Unfortunately, the result struct FunctionConfiguration does not implement Serialize trait, so cargo can not compile the code.

the code is like this:

let client = LambdaClient::new(&config);
let response = client.get_function().function_name(function_name).send().await?;
let configuration = response.configuration().unwrap();
let json_data = serde_json::to_string_pretty(&configuration)?;

the error message is:

error[E0277]: the trait bound `FunctionConfiguration: Serialize` is not satisfied
141  |         let json_data = serde_json::to_string_pretty(&configuration) {
     |                          ---------------------------- ^^^^^^^^^^^^^^ the trait `Serialize` is not implemented for `FunctionConfiguration

I don't want to manually implement the Serialize trait for the struct by myself, because there are so many similar structs in aws-sdk-rust, and each one has a complex nested structure.

how can I do? any suggestion?

Implementing Serialize for a type from a third party crate is indeed tedisome. I believe making a feature request for this while bridging the gap till it lands by patching the dependency with your own fork of the crate where you add derive(Serialize) for the types you need would possibly be the solution requiring the least amount of effort.

There are many APIs, each API has its own return structure type, and each structure has layers of nested substructures.
Even if this method can achieve the goal, the workload is very huge. I guess that this workload should be about the same as implementing serde::Serialize trait manually.
Are there any other better solutions?

Likely not. Deriving is just one attribute per struct, while implementing manually is either a one implementation per struct or a huge implementation for top-level struct, essentially inlining everything into it. derive(Serialize) (or cfg_attr(feature = "serde", derive(Serialize))) is a solution, in most cases.

1 Like

@jofas @Cerber-Ursi

I tried the above method, it works. Thanks.

the result file was generated:

{
    "function_name": "LMD-XXXX",
    "function_arn": "arn:aws:lambda:us-east-1:123456789999:function:LMD-XXXX",
    "runtime": "Python39",
    "role": "arn:aws:iam::123456789999:role/RL-LMD-XXXX",
    "handler": "lambda_function.lambda_handler",
    "code_size": 2048,
    "description": "",
    "timeout": 60,
    "memory_size": 128,
    "last_modified": "2024-03-22T07:30:35.551+0000",
    "code_sha256": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "version": "$LATEST",
    ......
}

But just for one API: get_function, 30+ files were modified...

modified:   ../Cargo.toml
modified:   primitives/sealed_enum_unknown.rs
modified:   types/_application_log_level.rs
modified:   types/_architecture.rs
modified:   types/_dead_letter_config.rs
modified:   types/_environment_error.rs
modified:   types/_environment_response.rs
modified:   types/_ephemeral_storage.rs
modified:   types/_file_system_config.rs
modified:   types/_function_configuration.rs
modified:   types/_image_config.rs
modified:   types/_image_config_error.rs
modified:   types/_image_config_response.rs
modified:   types/_last_update_status.rs
modified:   types/_last_update_status_reason_code.rs
modified:   types/_layer.rs
modified:   types/_log_format.rs
modified:   types/_logging_config.rs
modified:   types/_package_type.rs
modified:   types/_runtime.rs
modified:   types/_runtime_version_config.rs
modified:   types/_runtime_version_error.rs
modified:   types/_snap_start_apply_on.rs
modified:   types/_snap_start_optimization_status.rs
modified:   types/_snap_start_response.rs
modified:   types/_state.rs
modified:   types/_state_reason_code.rs
modified:   types/_system_log_level.rs
modified:   types/_tracing_config_response.rs
modified:   types/_tracing_mode.rs
modified:   types/_vpc_config_response.rs

Given that all these files AFAIK are generated, it's very likely that the real fix would be a one-line addition somewhere in the generator.

Yes,I agree with you.
But unfortunately, for the 3-party API library, I can not control how its code is generated. unless it provides the corresponding feature option...

I mean the fix by the library authors, yes. For you there seems to be no better solution than search-and-replace.

I found this RFC for the sdk for serialization and deserialization support which you might find interesting to read:

https://smithy-lang.github.io/smithy-rs/design/rfcs/rfc0030_serialization_and_deserialization.html

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.