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

如何在ASP.NET 5中启用转义JSON字符串解析?

ASP.NET 5全局解析转义JSON字符串方案

你的问题核心是请求体是包裹在字符串中的JSON对象,而默认JSON解析器直接期望目标类型的JSON结构,因此抛出转换异常。以下是两种全局生效的解决方案,分别适配System.Text.Json和Newtonsoft.Json:

一、使用System.Text.Json实现全局兼容

1. 编写通用转换器工厂

创建一个能处理所有复杂类型的转换器工厂,自动解析外层字符串包裹的JSON:

public class WrappedStringJsonConverterFactory : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert)
    {
        // 仅处理非基础类型(排除string、DateTime等)
        return !typeToConvert.IsPrimitive && typeToConvert != typeof(string) 
               && typeToConvert != typeof(DateTime) && typeToConvert != typeof(DateTimeOffset);
    }

    public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
    {
        return (JsonConverter)Activator.CreateInstance(
            typeof(WrappedStringJsonConverter<>).MakeGenericType(typeToConvert),
            BindingFlags.Instance | BindingFlags.Public,
            binder: null,
            args: new object[] { options },
            culture: null)!;
    }

    private class WrappedStringJsonConverter<T> : JsonConverter<T>
    {
        private readonly JsonSerializerOptions _options;

        public WrappedStringJsonConverter(JsonSerializerOptions options)
        {
            // 克隆配置避免递归调用
            _options = new JsonSerializerOptions(options);
            _options.Converters.RemoveAll(c => c.GetType() == typeof(WrappedStringJsonConverter<T>));
        }

        public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                var jsonStr = reader.GetString();
                return string.IsNullOrEmpty(jsonStr) ? default : JsonSerializer.Deserialize<T>(jsonStr, _options);
            }
            // 兼容直接发送对象JSON的场景
            return JsonSerializer.Deserialize<T>(ref reader, _options);
        }

        public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
        {
            JsonSerializer.Serialize(writer, value, options);
        }
    }
}

2. 全局注册转换器

在Program.cs中配置控制器时添加该转换器:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new WrappedStringJsonConverterFactory());
    });

var app = builder.Build();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

二、使用Newtonsoft.Json实现全局兼容

1. 编写通用转换器工厂

public class WrappedStringJsonConverter<T> : JsonConverter<T>
{
    public override T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            var jsonStr = reader.Value.ToString();
            return string.IsNullOrEmpty(jsonStr) ? default : JsonConvert.DeserializeObject<T>(jsonStr);
        }
        return serializer.Deserialize<T>(reader);
    }

    public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override bool CanWrite => true;
}

public class WrappedStringJsonConverterFactory : JsonConverterFactory
{
    public override bool CanConvert(Type objectType)
    {
        return !objectType.IsPrimitive && objectType != typeof(string) 
               && objectType != typeof(DateTime) && objectType != typeof(DateTimeOffset);
    }

    public override JsonConverter CreateConverter(Type objectType, JsonSerializer settings)
    {
        return (JsonConverter)Activator.CreateInstance(
            typeof(WrappedStringJsonConverter<>).MakeGenericType(objectType),
            BindingFlags.Instance | BindingFlags.Public,
            binder: null,
            args: null,
            culture: null)!;
    }
}

2. 全局注册转换器

在Program.cs中切换为Newtonsoft并添加转换器:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.Converters.Add(new WrappedStringJsonConverterFactory());
    });

var app = builder.Build();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

说明

两种方案都能同时兼容两种请求格式:

  • 直接发送TestClass的JSON对象(无外层字符串包裹)
  • 发送包裹在字符串中的JSON对象(即你当前curl请求的格式)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:50:09