3

I have a struct that uses an enum, but when printing it gives the enum name and the value instead of just the value. I want to serialize it using serde_json to send as a JSON request.

I want to re-use the struct for different commands to the geth json-rpc instead of making a different struct for every type of command. That's why I thought of using an enum. But I'm doing something wrong. It might be the printing but the json-rpc says the argument is invalid as well.

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
enum Params {
    String (String),
    Boolean (bool)
}

#[derive(Debug, Serialize, Deserialize)]
struct EthRequest {
    jsonrpc : String,
    method: String,
    params: [Params; 2],
    id: i32
}


fn main() {
   let new_eth_request = EthRequest {
        jsonrpc : "2.0".to_string(),
        method : "eth_getBlockByNumber".to_string(),
        params : [Params::String("latest".to_string()), Params::Boolean(true)],
        id : 1
    };
   println!("{:#?}", new_eth_request);

}

output:

EthRequest {
    jsonrpc: "2.0",
    method: "eth_getBlockByNumber",
    params: [
        String(
            "latest",
        ),
        Boolean(
            true,
        ),
    ],
    id: 1,
}

What I need is the params field to be params: ["latest",true]

DedicatedDreamer
  • 361
  • 5
  • 21
  • 2
    The output comes from the implementations of `Debug` (provided by the derive macro). If you want different output, either provide an alternative implementation of `Debug` or don't use the `:?` debug format specifier (and provide a `Display` implementation instead). But none of these formatting issues should affect serialisation with `serde_json`—so if that's your issue perhaps it would be better to show the relevant code and error relating to that? – eggyal Jun 16 '21 at 17:21
  • I used wireshark to follow the tcp-stream and it gives {"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":[{"String":"latest"},{"Boolean":true}],"id":1} – DedicatedDreamer Jun 16 '21 at 17:42

1 Answers1

3

The provided output is from the Debug implementation, not from serde. From serde you will get:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockByNumber",
  "params": [
    {
      "String": "latest"
    },
    {
      "Boolean": true
    }
  ],
  "id": 1
}

I guess you want to remove the tags String and Boolean in front of the enum values. That's pretty easy to do, just annotate your enum with #[serde(untagged)]:

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum Params {
    String (String),
    Boolean (bool)
}

And you will get the expected output:

{
  "jsonrpc": "2.0",
  "method": "eth_getBlockByNumber",
  "params": [
    "latest",
    true
  ],
  "id": 1
}

You can learn more about the different enum representations in serde's documentation.

Svetlin Zarev
  • 14,713
  • 4
  • 53
  • 82