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

C# .NET中解析AWS SNS消息对象失败,请求技术排查

问题:C# .NET中AWS SNS消息JSON解析失败

在使用Newtonsoft.Json解析AWS SNS消息的JSON字符串时,无法反序列化为自定义实体类,出现解析错误。

获取到的JSON字符串(messageBody)

{
  "Type" : "Nti_1",
  "MessageId" : "c1b7cd5b-3099-532e-9539-91376eea607b",
  "SequenceNumber" : "10000000000000128000",
  "TopicArn" : "arn:aws:sns:us-east-1:xxxxxxx:Project1-SNS.fifo",
  "Message" : "{'Prop1':'202020','Prop2':'Hi-I again reached','Prop3':'Testing String'}",
  "Timestamp" : "2023-02-05T07:35:15.905Z",
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:xxxxxx:PushNotification-SNS.fifo:08d0fac2-ac0f-4ff9-b583-61024a98672d",
  "MessageAttributes" : {
    "EventType" : {"Type":"String.Array","Value":"["SMS","ArialRoot"]"}
  }
}

自定义的C#实体类

public class ParentObject
{
    public string Type { get; set; }
    public string MessageId { get; set; }
    public string SequenceNumber { get; set; }

    public string TopicArn { get; set; }

    public ChildObject Message { get; set; }
    public string Timestamp { get; set; }

    public string UnsubscribeURL { get; set; }

    public string MessageAttributes { get; set; }
}

public class ChildObject
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
}

解析代码

ParentObject obj = JsonConvert.DeserializeObject<ParentObject>(messageBody);

解析失败的原因

  1. Message字段格式与类型不匹配:

    • 原始JSON中Message的值用单引号包裹,不符合标准JSON的双引号要求,本身是非法JSON片段。
    • 即使格式合法,Message是字符串类型的JSON片段,直接映射到ChildObject类型会失败,JsonConvert默认不会自动将字符串解析为嵌套对象。
  2. MessageAttributes类型定义错误:
    原始JSON中MessageAttributes是嵌套对象,但代码中定义为string类型,类型不匹配导致解析失败。

  3. MessageAttributes.EventType.Value格式错误:
    Value字段的值"["SMS","ArialRoot"]"内部双引号未转义,属于非法JSON语法,会导致整个JSON解析失败。


解决方案

步骤1:修复原始JSON格式(若可控制消息发送端)

  • 将Message字段的单引号替换为双引号,修正为合法JSON字符串:"{\"Prop1\":\"202020\",\"Prop2\":\"Hi-I again reached\",\"Prop3\":\"Testing String\"}"
  • 修正MessageAttributes.EventType.Value的格式,转义内部双引号:"[\"SMS\",\"ArialRoot\"]"

步骤2:调整C#实体类定义

修正MessageAttributes的类型,并处理Message字段的嵌套解析:

方式1:二次解析Message字段

先将Message定义为字符串,解析完成后再二次反序列化为ChildObject:

public class ParentObject
{
    public string Type { get; set; }
    public string MessageId { get; set; }
    public string SequenceNumber { get; set; }
    public string TopicArn { get; set; }
    // 先定义为字符串,后续二次解析
    public string Message { get; set; }
    public string Timestamp { get; set; }
    public string UnsubscribeURL { get; set; }
    // 定义匹配的MessageAttributes实体类
    public MessageAttributes MessageAttributes { get; set; }
}

public class MessageAttributes
{
    public EventType EventType { get; set; }
}

public class EventType
{
    public string Type { get; set; }
    // 若Value是数组字符串,可定义为string后续解析;格式正确也可直接定义为string[]
    public string Value { get; set; }
}

public class ChildObject
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
}

解析代码:

// 先解析父对象
var parentObj = JsonConvert.DeserializeObject<ParentObject>(messageBody);
// 处理Message字段的单引号问题(若无法修改发送端,手动替换)
var cleanedMessage = parentObj.Message.Replace("'", "\"");
// 二次解析为ChildObject
var childObj = JsonConvert.DeserializeObject<ChildObject>(cleanedMessage);
// 处理MessageAttributes的Value数组
var eventTypes = JsonConvert.DeserializeObject<string[]>(parentObj.MessageAttributes.EventType.Value.Replace("'", "\""));

方式2:使用JsonConverter自动解析Message字段

自定义转换器处理Message字段的字符串到ChildObject的解析:

public class StringToChildObjectConverter : JsonConverter<ChildObject>
{
    public override ChildObject ReadJson(JsonReader reader, Type objectType, ChildObject existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var messageStr = reader.Value.ToString();
        // 替换单引号为双引号,修正格式
        var cleanedStr = messageStr.Replace("'", "\"");
        return JsonConvert.DeserializeObject<ChildObject>(cleanedStr);
    }

    public override void WriteJson(JsonWriter writer, ChildObject value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

修改ParentObject的Message字段:

public class ParentObject
{
    // 其他字段不变
    [JsonConverter(typeof(StringToChildObjectConverter))]
    public ChildObject Message { get; set; }
    public MessageAttributes MessageAttributes { get; set; }
}

此时直接调用原解析代码即可:

ParentObject obj = JsonConvert.DeserializeObject<ParentObject>(messageBody);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:55:17