Serialization of nested items for Stripe

Hi,

I’m trying to send a request to Stripe using HttpClient. In general my gateway looks like this one in the sample: https://github.com/ServiceStack/ServiceStack.Text/blob/ee06690f035e196fa522bf281a033beaa590c1d7/tests/ServiceStack.Text.Tests/UseCases/StripeGateway.cs#L566

So underlying I’m using QueryStringSerializer with FormUrlEncoded strategy for the complex types and I’m stuck a bit with the nested objects. That serialiser works fine for 2 levels of nesting but produces not acceptible value by Stripe on the 3rd level. I have the following objects:

public class PaymentIntentCreateRequest 
{
    [DataMember(Name = "mandate_data")]
    public MandateDataModel? MandateData { get; init; }
}

public sealed record MandateDataModel
{
    [DataMember(Name = "customer_acceptance")]
    public CustomerAcceptanceModel CustomerAcceptance { get; init; }
}

public sealed record CustomerAcceptanceModel
{
    [DataMember(Name = "type")]
    public MandateTypes Type { get; init; }

    [DataMember(Name = "accepted_at")]
    public DateTime? AcceptedAt { get; init; }

    [DataMember(Name = "offline")]
    public string? Offline { get; init; }

    [DataMember(Name = "online")]
    public OnlineMandateModel? Online { get; init; }
}

public sealed record OnlineMandateModel
{
    [DataMember(Name = "ip_address")]
    public string IpAddress { get; init; }

    [DataMember(Name = "user_agent")]
    public string UserAgent { get; init; }
}

For this structure I get the following serialized body:

mandate_data[customer_acceptance][type]=online
&mandate_data[customer_acceptance][accepted_at]=1652908159
&mandate_data[customer_acceptance][online]={ip_address:%3a%3a1,user_agent:customAgent}

but Stripe requires it like:

mandate_data[customer_acceptance][type]=online
&mandate_data[customer_acceptance][accepted_at]=1652908159
&mandate_data[customer_acceptance][online][ip_address]=%3a%3a1
&mandate_data[customer_acceptance][online][user_agent]=customAgent

So my question is is there a way to change the serializer behavior to control the nesting level or any other workarounds to reach a result?

The way to customize the URL that’s used is to add [IgnoreDataMember] to ignore the property from serialization then manually add it to the URL by overriding the ToUrl() method, e.g: