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);
}
所以 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);
}