Azure PubSub / JSON 子协议 / 反序列化 JSON 负载

Azure PubSub / JSON subprotocol / deserialize JSON payload

所以 JSON 会存在一段时间,我将不得不学习它是如何解决问题的....

在 Azure pubsub 中,我发送这样的消息:

 var json = System.Text.Json.JsonSerializer.Serialize(<<a class in C#>> );
 await webPubSubServiceClient.SendToAllAsync(content: json, contentType: 
  ContentType.ApplicationJson);

当我在另一边得到它时(从 ResponseMessage.TEXT 读取),我得到这个:

{
  "type": "message",
  "from": "server",
  "dataType": "json", //binary/json/text
  "data": {
    "event": "connected",
    "userId": "WPFClient_162035",
    "connectionId": "",
    "message": "User: >WPFClient_162035< has joined hub:>chat<",
    "type": "system",
    "group": "",
    "typeName": "WebhostGeneratedMessage"
  }
}

webPubSubServiceClient 已经包装了我在这个结构中创建的JSON:

 {
      "type": "message",
      "from": "server",
      "dataType": "json", //binary/json/text
      "data": {}

这个问题是我正在发送各种 JSON 有效载荷,并且包装器没有信封字段 告诉我如何反序列化“数据”中的内容 - 就像在其中class 我有一个基础 class 和一个 属性 来填充我正在使用的 typeName。

所以当我这样做时:

TypeOfMessageReceived? deserialized = System.Text.Json.JsonSerializer.Deserialize<TypeOfMessageReceived>(body);

反序列化在数据元素上有爆炸的变化,因为数据元素可以是我序列化的任何class。

那么如何在 C# 中使用 class 读取数据?我是否将其阅读为 JSONElement/JSONDocument 并解析我的方式?如果是这样,我希望有一些最佳实践的例子。

我想我的另一个选择是简单地将发送的消息定义为“TEXT”,然后反序列化到一个基class,获取我需要的段,反序列化那个片段?

我在这里遗漏了一些东西,因为 JSON 协议应该在这里帮助我,而不是妨碍我......或者我只是认为类型太强了?

我正在使用 NET6,所以我希望我们有一些我不知道的新功能。正如我所说,我正在寻找使用这项新服务的最佳实践。

提前致谢。

如何先检查 typeName 然后反序列化为强类型:

using (var document = JsonDocument.Parse(inputMessage))
{
    var type = document.RootElement.GetProperty("type").GetString();
    if (type == "message")
    {
        var data = document.RootElement.GetProperty("data");
        if (data.ValueKind == JsonValueKind.Object && data.TryGetProperty("typeName", out var typeNameProperty))
        {
            var typeName = typeNameProperty.GetString();
            if (typeName == "WebhostGeneratedMessage")
            {
                var message = data.Deserialize<WebhostGeneratedMessage>(new JsonSerializerOptions(JsonSerializerDefaults.Web));

                Console.WriteLine(message?.Message ?? throw new ArgumentNullException());
            }
        }
    }
}

一个完整的可运行 net6 控制台测试应用程序:


using System.Text.Json;

var inputMessage = JsonSerializer.Serialize(
    new
    {
        type = "message",
        from = "server",
        dataType = "json",
        data = new
        {
            @event = "connected",
            userId = "WPFCLient_142322",
            connectionId = "12345",
            message = "User a joined",
            type = "system",
            group = "group1",
            typeName = "WebhostGeneratedMessage"

        }
    });

using (var document = JsonDocument.Parse(inputMessage))
{
    var type = document.RootElement.GetProperty("type").GetString();
    if (type == "message")
    {
        var data = document.RootElement.GetProperty("data");
        if (data.ValueKind == JsonValueKind.Object && data.TryGetProperty("typeName", out var typeNameProperty))
        {
            var typeName = typeNameProperty.GetString();
            if (typeName == "WebhostGeneratedMessage")
            {
                var message = data.Deserialize<WebhostGeneratedMessage>(new JsonSerializerOptions(JsonSerializerDefaults.Web));

                Console.WriteLine(message?.Message ?? throw new ArgumentNullException());
            }
        }
    }
}

public class WebhostGeneratedMessage
{
    public string? Event { get; set; }
    public string? UserId { get; set; }
    public string? ConnectionId { get; set; }
    public string? Message { get; set; }
    public string? Type { get; set; }
    public string? Group { get; set; }
    public string? TypeName { get; set; } = nameof(WebhostGeneratedMessage);
}