You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ServiceStack按预期序列化隐式字符串重载类型?

问题描述

我编写了一个Base64UrlString类,用于确保服务收发的字符串无需额外编码即可保持URL安全,期望只需在DTO中使用该类型,ServiceStack就能自动识别并使用其隐式运算符。

DTO代码:

public class MyDto {
    Base64UrlString myString;
}

var dto = new MyDto() { myString = "hello i am url safe"; }

但客户端接收时,myString的值为{}。是否有更优雅的实现方式?原本以为这样使用类型就能“直接生效”。

Base64UrlString类代码:

// used only for Base64UrlEncoder
using Microsoft.IdentityModel.Tokens;

namespace MyDto.ServiceModel.Types
{
    public class Base64UrlString
    {
        private readonly string _base64UrlString;

        public Base64UrlString(string str)
        {
            _base64UrlString = Base64UrlEncoder.Encode(str);
        }

        public static implicit operator string(Base64UrlString base64UrlString) => base64UrlString.ToString();
        public static implicit operator Base64UrlString(string str) => new(str);

        public override string ToString() => Base64UrlEncoder.Decode(_base64UrlString);
    }
}
解决方案

出现{}的原因有两个:一是DTO中的字段未设为公共成员,ServiceStack默认只序列化公共属性/字段;二是ServiceStack无法自动识别自定义类型的隐式转换,需要明确告知序列化器如何处理该类型。

步骤1:修正DTO的访问权限

将DTO中的字段改为公共属性,确保ServiceStack能识别并序列化:

public class MyDto {
    public Base64UrlString MyString { get; set; }
}

步骤2:让自定义类型支持ServiceStack序列化

修改Base64UrlString类,实现ServiceStack的ISerializeToString接口,同时调整构造逻辑避免重复编码:

using Microsoft.IdentityModel.Tokens;
using ServiceStack;

namespace MyDto.ServiceModel.Types
{
    public class Base64UrlString : ISerializeToString
    {
        private string _base64UrlEncoded;

        // 用于原始字符串编码的构造函数
        public Base64UrlString(string str)
        {
            _base64UrlEncoded = Base64UrlEncoder.Encode(str);
        }

        // 用于反序列化的私有构造函数,避免重复编码
        private Base64UrlString() { }

        public static implicit operator string(Base64UrlString value) => value.ToString();
        public static implicit operator Base64UrlString(string str) => new(str);

        public override string ToString() => Base64UrlEncoder.Decode(_base64UrlEncoded);

        // 序列化时输出编码后的Base64Url安全字符串
        public string SerializeToString() => _base64UrlEncoded;

        // 反序列化时从已编码的字符串创建实例
        public static Base64UrlString FromEncodedString(string encodedStr) 
        {
            return new Base64UrlString { _base64UrlEncoded = encodedStr };
        }
    }
}

步骤3:注册反序列化转换器

在ServiceStack的AppHost配置中,注册Base64UrlString的反序列化逻辑:

public override void Configure(Container container)
{
    // 注册自定义类型的反序列化转换器
    TypeSerializer.RegisterDeserializer<Base64UrlString>(Base64UrlString.FromEncodedString);
}

补充说明

  • 实现ISerializeToString后,ServiceStack序列化时会直接调用SerializeToString()输出编码后的安全字符串,无需手动编码。
  • 注册反序列化转换器后,ServiceStack接收字符串时会自动转换为Base64UrlString实例,无需额外处理。
  • 新增私有构造函数是为了在反序列化时直接复用已编码的字符串,避免重复执行编码逻辑。

内容的提问来源于stack exchange,提问作者Jan Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 12:31:03