Заставить serde создавать только шестнадцатеричные строки для удобочитаемого сериализатора?

#rust #serde #serde-json #bincode

Вопрос:

В настоящее время я использую serde-hex.

 use serde_hex::{SerHex,StrictPfx,CompactPfx};

#[derive(Debug,PartialEq,Eq,Serialize,Deserialize)]
struct Foo {
    #[serde(with = "SerHex::<StrictPfx>")]
    bar: [u8;4],
    #[serde(with = "SerHex::<CompactPfx>")]
    bin: u64
}

fn it_works() {
    let foo = Foo { bar: [0,1,2,3], bin: 16 };
    let ser = serde_json::to_string(amp;foo).unwrap();
    let exp = r#"{"bar":"0x00010203","bin":"0x10"}"#;
    assert_eq!(ser,exp);

    // this fails
    let binser = bincode::serialize(amp;foo).unwrap();
    let binexp: [u8; 12] = [0, 1, 2, 3, 16, 0, 0, 0, 0, 0, 0, 0];
    assert_eq!(binser,binexp);
}
 

терпит неудачу с:

 thread 'wire::era::tests::it_works' panicked at 'assertion failed: `(left == right)`
  left: `[10, 0, 0, 0, 0, 0, 0, 0, 48, 120, 48, 48, 48, 49, 48, 50, 48, 51, 4, 0, 0, 0, 0, 0, 0, 0, 48, 120, 49, 48]`,
 right: `[0, 1, 2, 3, 16, 0, 0, 0, 0, 0, 0, 0]`', src/test.rs:20:9
 

потому что он расширил значения до шестнадцатеричных строк для бинкода.

У меня есть много структур, которые мне нужно сериализовать как с помощью serde_json, так и с помощью bincode. serde_hex делает именно то, что мне нужно для сериализации JSON. При использовании bincode serde-hex по-прежнему преобразует массивы в шестнадцатеричные строки, что нежелательно.

Я замечаю, что secp256k1 использует d.is_human_readable() .

Как я могу подать serde_hex заявку только на serde_json и быть проигнорированным bincode ?

Ответ №1:

Реализация функции, используемой с атрибутом serde with, в основном является шаблонной и выглядит следующим образом. Это только отличает удобочитаемый формат от других форматов. Если вам нужен более детальный контроль, вы можете вместо этого перейти к локальной переменной потока.

 fn serialize_hex<S>(v: amp;u64, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    if serializer.is_human_readable() {
        serde_hex::SerHex::<serde_hex::StrictPfx>::serialize(v, serializer)
    } else {
        v.serialize(serializer)
    }
}

// use like
// #[serde(serialize_with = "serialize_hex")]
// bin: u64
 

Фрагмент кода можно было бы улучшить, превратив u64 его в универсальный.