Crate serde_metaform

Crate serde_metaform 

Source
Expand description

A serde serializer for the “Form + JSON” encoding format.

This crate provides a robust serde serializer for a specific hybrid data format used by some web APIs, most notably Meta’s. This is not a standard application/x-www-form-urlencoded implementation; it follows a unique set of rules where values are encoded as JSON.

The serializer is designed to be efficient and stream-based, performing the JSON serialization and percent-encoding in a single pass without creating intermediate string representations of the entire data structure.

§The “Form + JSON” Format

The format can be conceptually understood as a standard form-encoded payload where each value has been replaced by its JSON representation.

§Format Rules

  1. Top-Level Structure: The root data structure must be a key-value pair collection, such as a Rust struct, a map, or an enum variant that holds data (newtype, struct, or tuple variants). Primitives (like u32) or simple sequences (like Vec<u32>) are not valid at the top level.

  2. Key Serialization: Each key is converted to a string and then percent-encoded. The keys are never quoted.

  3. Value Serialization: Each value is serialized to a JSON string, and that resulting JSON string is then percent-encoded.

    • Simple types like numbers, booleans, and strings become their direct JSON counterparts (e.g., 123, true, "hello world").
    • Complex types like structs, maps, and vectors become JSON objects ({...}) or arrays ([...]).
  4. Separators: Key-value pairs are joined by &, and each key is separated from its value by =.


§A Note on Compatibility

⚠️ Warning: This format is highly specific. Do not use this serializer to send data to a standard web server expecting application/x-www-form-urlencoded. A server that isn’t explicitly designed to parse JSON-encoded values from a form payload will not be able to understand the output of this crate.

§Examples

§Simple Struct

For simple values, the output looks very similar to standard form encoding.

use serde::Serialize;
use serde_metaform::to_string;

#[derive(Serialize)]
struct User {
    id: u64,
    username: String,
    is_verified: bool,
}

let user = User {
    id: 9001,
    username: "gordon_freeman".to_string(),
    is_verified: false,
};

let encoded = to_string(&user).unwrap();

// The values 9001, "gordon_freeman", and false are serialized as JSON primitives.
assert_eq!(encoded, "id=9001&username=gordon_freeman&is_verified=false");

§Complex Nested Data and Enums

The power of this format becomes clear with complex, nested data.

use serde::Serialize;
use serde_metaform::to_string;

#[derive(Serialize)]
struct Attachment {
    type_: String,
    url: String,
}

#[derive(Serialize)]
enum Message {
    Text(String),
    WithAttachment {
        text: String,
        attachment: Attachment,
    },
}

let message = Message::WithAttachment {
    text: "Check this out!".to_string(),
    attachment: Attachment {
        type_: "image".to_string(),
        url: "https://example.com/img.png".to_string(),
    },
};

let encoded = to_string(&message).unwrap();

// The key is the enum variant name: "WithAttachment".
// The value is the entire associated struct, serialized to JSON:
// {"text":"Check this out!","attachment":{"type_":"image","url":"https://example.com/img.png"}}
// ...and then that JSON string is percent-encoded.

let expected_value = "%7B%22text%22%3A%22Check%20this%20out%21%22%2C%22attachment%22%3A%7B%22type_%22%3A%22image%22%2C%22url%22%3A%22https%3A%2F%2Fexample.com%2Fimg.png%22%7D%7D";
let expected_string = format!("WithAttachment={}", expected_value);

assert_eq!(encoded, expected_string);

Modules§

error

Structs§

DisplaySerializer
A wrapper struct that implements std::fmt::Display for any serde::Serialize type.
Serializer
The main serializer for the “Form + JSON” format.

Functions§

display
Creates a displayable wrapper for a serializable type.
to_string
Serializes the given data structure as a String.
to_vec
Serializes the given data structure as a vector of bytes (Vec<u8>).
to_writer
Serializes the given data structure into the provided writer.