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

System.Text.Json反序列化自定义结构体属性转换失败问题

问题根因

System.Text.Json 内置的类型转换逻辑 不会自动调用C#自定义的隐式/显式类型转换运算符,这是它和Newtonsoft.Json的核心行为差异之一。
当前代码里的Side自定义结构体仅实现了Side -> string方向的隐式转换,既没有实现反向string -> Side的转换逻辑,也没有向STJ提供专属的类型转换规则,反序列化遇到JSON中"S": "BUY"的字符串值时,STJ找不到从string到Side的内置转换路径,直接抛出JsonException。

修复方案

给Side类型实现专属的JsonConverter<Side>,明确告诉STJ怎么完成字符串和Side实例的双向转换,步骤如下:

  • 第一步:编写自定义转换器
using System.Text.Json;
using System.Text.Json.Serialization;

public class SideJsonConverter : JsonConverter<Side>
{
    public override Side Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.String)
            throw new JsonException($"Side字段期望字符串类型值,实际收到{reader.TokenType}类型");
        
        string? value = reader.GetString();
        return value switch
        {
            "BUY" => Side.Buy,
            "SELL" => Side.Sell,
            _ => throw new JsonException($"不支持的Side值:{value}")
        };
    }

    public override void Write(Utf8JsonWriter writer, Side value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.Value);
    }
}
  • 第二步:注册转换器,二选一即可:
    • 方式一:给Side结构体加特性,全局所有用到Side类型的序列化/反序列化场景自动生效
    [JsonConverter(typeof(SideJsonConverter))]
    public readonly struct Side
    {
        // 原有代码保持不变,可按需补充string到Side的隐式转换方便业务代码使用
        public static implicit operator Side(string value)
        {
            return value switch
            {
                "BUY" => Buy,
                "SELL" => Sell,
                _ => throw new ArgumentOutOfRangeException(nameof(value), $"未知交易方向值:{value}")
            };
        }
    
        // 其余原有结构体代码保持不变
        private Side(string value)
        {
            Value = value;
        }
    
        public static Side Buy => new("BUY");
        public static Side Sell => new("SELL");
    
        public string Value { get; }
    
        public static implicit operator string(Side enm)
        {
            return enm.Value;
        }
    
        public override string ToString()
        {
            return Value;
        }
    }
    
    • 方式二:仅给BinanceStreamOrderUpdate的Side属性加特性,只对该属性的反序列化生效
    [JsonPropertyName("S")]
    [JsonConverter(typeof(SideJsonConverter))]
    public Side Side { get; init; }
    
额外注意

你代码中其他和Side类似的自定义结构体类型(比如SpotOrderType、TimeInForce、ExecutionType等),如果也是类似的字符串映射自定义值类型实现,都需要按同样方式编写专属JsonConverter,否则会触发同类转换异常。
如果这些类型是C#原生枚举类型,STJ默认会按数值做序列化/反序列化,要匹配接口返回的字符串值,给枚举类型加[JsonStringEnumConverter]特性即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:18:19