Serde json rename keys

Is there a way I can remove first character from json key with serde when parsing from string.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9f2d49977cae64b0ad90cbccce491662

I want my println to stay the same and when serializing string, I want to remove first character.

Is something like this good enough?

use serde_json::Result;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct MyObject {
    #[serde(rename="@name")]
    name: String,
    #[serde(rename="@age")]
    age: u32,
    #[serde(rename="@phones")]
    phones: Vec<String>,
}

fn example () -> Result<()> {
    let data = r#"
        {
            "@name": "John Doe",
            "@age": 43,
            "@phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into serde_json::Value.
    let v: MyObject = serde_json::from_str(data)?;
    
    // Access parts of the data by indexing with square brackets.
    println!("Please call {} at the number {}", v.name, v.phones[0]);

    Ok(())
}

fn main() {
    example().unwrap();
}

You can use serde_with::with_prefix! to apply a prefix to all fields of a struct.

You need to use a wrapper struct around your actual struct, however, this wrapper can be generic such that you can use it for any struct/enum which needs the prefix applied.

serde_with::with_prefix!(prefix_at "@");

#[derive(Debug, Serialize, Deserialize)]
struct Obj {
    name: String,
    age: u32,
    phones: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>"))]
struct Prefix<T>(#[serde(with = "prefix_at")] T);

let json = r#"
{
    "@name": "John Doe",
    "@age": 43,
    "@phones": [
        "+44 1234567",
        "+44 2345678"
    ]
}"#;

serde_json::from_str::<Prefix<Obj>>(json).unwrap()
1 Like

I would using for parsing db fields..property can truly be anything. Building generic is not good enough unfortunately

1 Like

It will be used for parsing db fields in a driver. I won't havve struct

1 Like

Maybe you can explain your problem in more detail and why the Prefix struct won't work in your case. You only need to use it where you perform the serialization or deserialization steps and other code does not need to know about it. You can also deserialize a Prefix<serde_json::Value> if you cannot deserialize into a struct.

This is the how you can adapt your example while keeping the println line identical.

fn example () -> Result<(), serde_json::Error> {
    serde_with::with_prefix!(prefix_at "@");
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>"))]
    struct Prefix<T>(#[serde(with = "prefix_at")] T);
    
    let data = r#"
        {
            "@name": "John Doe",
            "@age": 43,
            "@phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into serde_json::Value.
    let v: serde_json::Value = serde_json::from_str::<Prefix<_>>(data)?.0;
    
    // Access parts of the data by indexing with square brackets.
    println!("Please call {} at the number {}", v["name"], v["phones"][0]);
    
    // You can also serialize in the same way
    println!("{}", serde_json::to_string_pretty(&Prefix(&v)).unwrap());

    Ok(())
}