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

C#反序列化含内嵌大括号字符串的JSON时Data字段解析异常处理

问题根因

反序列化失败和Data属性的类型、[JsonIgnore]配置没有任何关系。核心问题是上游返回的JSON本身不符合RFC 8259语法规范:
标准JSON要求字符串值内部的双引号必须加反斜杠转义,但你收到的payload里Data字段是被双引号包裹的JSON片段,片段内部的双引号完全未做转义。JSON解析器读到Data值的开头双引号后,遇到{后第一个未转义的双引号(即Employee_ID字段前的引号)就会判定当前字符串已结束,后续内容直接触发词法解析错误——这个阶段发生在属性匹配逻辑之前,所以任何针对实体类属性的特性配置都不会生效。


可行解决方案

方案1:不需要使用Data字段时的最快修复(兼容所有JSON序列化库)

不需要折腾序列化器配置,直接对原始JSON字符串做预处理修复语法即可,性能开销极低,完全满足你不需要读取Data内容的需求:

using System.Text.RegularExpressions;

// 读取到的原始JSON响应字符串
string rawJson = await httpClient.GetStringAsync(requestUrl);
// 正则匹配非法格式的Data字段,替换为合法的null值
string fixedJson = Regex.Replace(
    rawJson, 
    @"""Data""\s*:\s*""\{.*?\}"",", 
    "\"Data\":null,", 
    RegexOptions.Singleline
);
// 后续走正常反序列化逻辑即可,[JsonIgnore]特性也能正常生效
var result = JsonSerializer.Deserialize<OutsideEvent>(fixedJson);

方案2:需要解析Data字段内容的处理方式

如果你后续需要用到Data内的员工信息,可以根据你使用的序列化库做配置,直接将嵌套内容映射为强类型对象:

适配Newtonsoft.Json(Json.NET)

  1. 修改实体类,将Data属性改为强类型,添加自定义转换器:
public class OutsideEvent
{
    public string Event_Id { get; set; }
    public string Event_Name { get; set; }
    // 注意:原int类型存在时间戳溢出风险,建议改为long兼容13位毫秒级时间戳
    public long Event_DateTime { get; set; }
    public string ClientCode { get; set; }
    public string Resource_Field { get; set; }
    public object Resource_Identifier { get; set; }
    public object Object { get; set; }
    public string? Object_Identifier { get; set; }

    [JsonConverter(typeof(NestedJsonConverter<eventData>))]
    public eventData? Data { get; set; }

    public string Endpoint { get; set; }
    public string EndpointUrl { get; set; }
}
  1. 实现自定义转换器,处理嵌套JSON的二次解析:
public class NestedJsonConverter<T> : JsonConverter<T>
{
    public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        string rawContent = reader.ReadAsString();
        return string.IsNullOrWhiteSpace(rawContent) ? default : JsonConvert.DeserializeObject<T>(rawContent);
    }

    public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
    {
        writer.WriteValue(JsonConvert.SerializeObject(value));
    }
}
  1. 反序列化时开启容错配置:
var settings = new JsonSerializerSettings
{
    CheckAdditionalContent = false,
    Error = (sender, args) =>
    {
        if (args.ErrorContext.Path == nameof(OutsideEvent.Data))
            args.ErrorContext.Handled = true;
    }
};
var result = JsonConvert.DeserializeObject<OutsideEvent>(rawJson, settings);

适配.NET默认System.Text.Json

  1. 实体类修改逻辑和上述一致,添加对应版本的自定义转换器:
public class NestedJsonConverterSTJ<T> : JsonConverter<T>
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        string rawContent = doc.RootElement.GetRawText().Trim('"');
        return string.IsNullOrWhiteSpace(rawContent) ? default : JsonSerializer.Deserialize<T>(rawContent, options);
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(JsonSerializer.Serialize(value, options));
    }
}
  1. 反序列化时开启宽松解析配置:
var options = new JsonSerializerOptions
{
    AllowTrailingCommas = true,
    ReadCommentHandling = JsonCommentHandling.Skip,
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var result = JsonSerializer.Deserialize<OutsideEvent>(rawJson, options);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:09:27