将来自服务总线队列触发器的 JSON 消息反序列化为 C# 对象
Deserialize JSON message from Service Bus Queue Trigger to C# Object
我有一个如下所示的 Azure 函数:
public class SaveProductDataToDatabase
{
private readonly IProductRepository _productRepository;
public SaveProductDataToDatabase(IProductRepository productRepository)
{
_productRepository = productRepository;
}
[FunctionName("SaveProductDataToDatabase")]
public void Run([ServiceBusTrigger("product-data-dev-01", Connection = "ServiceBusConnectionString")] string myQueueItem, ILogger log)
{
log.LogInformation($"Processed message: {myQueueItem}");
// TODO : JSON Mapping will be added here once Service Bus Queue is Up and Running.
_productRepository.Add(new Domain.Entities.Product());
}
}
这里,myQueueItem
会return一个复杂的嵌套JSON字符串
{
"metadata": {
"origin": "xyz-data",
"dateCreated": "2022-03-17T12:48:04.511Z"
},
"version": 6,
"messageId": "a44f23aa-bab4-4eed-a235-5820d966f669",
"sWrapper": {
"sid": "zzavqw18",
"identifiers": [
{
"alias": "si-sku",
"value": [
"8086300"
]
}
]
},
"itemType": "ITEM",
"master": {
"masterSource": "XYZ_PDS",
"title": {
"mainTitle": "XYZ - All Time Greats"
},
"description": {
"longDescription": "XYZ - All Time Greats",
"shortDescription": "XZY - All Time Greats"
},
"classification": {
"identifier": "1pvfy"
}
}
}
在此,我想提取 sWrapper.sid
、sWrapper.identifiers.value
和 classification.identifier
属性并将其分配给纯 C# 对象。该对象将传递给 _productRepository.Add(<C# object goes here>);
如何处理这个映射?什么是最好的方法?请指教
有多种方法。
选项 1 - 使用 class 反序列化并使用 class 属性使用 Newtonsoft.Json
JsonConvert.DeserializeObject<CLASS>(JSON_STRING)
选项 2
使用 System.Text.Json.Nodes 直接访问节点
var jn = JsonNode.Parse(j)["sWrapper"].Dump("node");
jn["sid"].GetValue<string>().Dump("Value of SID");
P.S> 同样,有可能的方法...
然后创建一个新的 class 并使用值填充 class 属性并将对象传递给函数。
这是使用 Cinchoo ETL 从 JSON 中选择节点的另一种方法 - 一个开源库
定义 POCO class 属性以及 JSON 路径
public class QueueItem
{
[ChoJSONPath("sWrapper.sid")]
public string SID { get; set; }
[ChoJSONPath("sWrapper.identifiers[0].value[0]")]
public string IdentifierValue { get; set; }
[ChoJSONPath("master.classification.identifier")]
public string ClassificationIdentifier { get; set; }
}
然后使用库反序列化JSON如下
using (var r = ChoJSONReader<QueueItem>.LoadText(json))
{
r.Print();
}
样本fiddle:https://dotnetfiddle.net/K7GnT8
正如其他人所提到的,您可以创建一个 class/classes 来表示您希望从服务总线消息中获取的信息。
public class ServiceBusMessage
{
[JsonPropertyName("sWrapper")]
public SWrapper SWrapper { get; set; }
[JsonPropertyName("classification")]
public Classification Classification { get; set; }
}
public class SWrapper
{
[JsonPropertyName("sid")]
public string Sid { get; set; }
[JsonPropertyName("identifiers")]
public SWrapperIdentifier[] Identifiers { get; set; }
}
public class SWrapperIdentifier
{
[JsonPropertyName("value")]
public string[] Value { get; set; }
}
public class Classification
{
[JsonPropertyName("identifier")]
public string Identifier { get; set; }
}
此外,如果您的 Azure Function 是 2.0 或更高版本,您可以将函数签名更改为:
public void Run([ServiceBusTrigger("product-data-dev-01", Connection = "ServiceBusConnectionString")] ServiceBusMessage myQueueItem, ILogger log)
框架将为您处理反序列化(根据 these 文档)。
然后您可以将这个“请求”对象映射到任何您想要使用的结构。
我有一个如下所示的 Azure 函数:
public class SaveProductDataToDatabase
{
private readonly IProductRepository _productRepository;
public SaveProductDataToDatabase(IProductRepository productRepository)
{
_productRepository = productRepository;
}
[FunctionName("SaveProductDataToDatabase")]
public void Run([ServiceBusTrigger("product-data-dev-01", Connection = "ServiceBusConnectionString")] string myQueueItem, ILogger log)
{
log.LogInformation($"Processed message: {myQueueItem}");
// TODO : JSON Mapping will be added here once Service Bus Queue is Up and Running.
_productRepository.Add(new Domain.Entities.Product());
}
}
这里,myQueueItem
会return一个复杂的嵌套JSON字符串
{
"metadata": {
"origin": "xyz-data",
"dateCreated": "2022-03-17T12:48:04.511Z"
},
"version": 6,
"messageId": "a44f23aa-bab4-4eed-a235-5820d966f669",
"sWrapper": {
"sid": "zzavqw18",
"identifiers": [
{
"alias": "si-sku",
"value": [
"8086300"
]
}
]
},
"itemType": "ITEM",
"master": {
"masterSource": "XYZ_PDS",
"title": {
"mainTitle": "XYZ - All Time Greats"
},
"description": {
"longDescription": "XYZ - All Time Greats",
"shortDescription": "XZY - All Time Greats"
},
"classification": {
"identifier": "1pvfy"
}
}
}
在此,我想提取 sWrapper.sid
、sWrapper.identifiers.value
和 classification.identifier
属性并将其分配给纯 C# 对象。该对象将传递给 _productRepository.Add(<C# object goes here>);
如何处理这个映射?什么是最好的方法?请指教
有多种方法。 选项 1 - 使用 class 反序列化并使用 class 属性使用 Newtonsoft.Json
JsonConvert.DeserializeObject<CLASS>(JSON_STRING)
选项 2 使用 System.Text.Json.Nodes 直接访问节点
var jn = JsonNode.Parse(j)["sWrapper"].Dump("node");
jn["sid"].GetValue<string>().Dump("Value of SID");
P.S> 同样,有可能的方法... 然后创建一个新的 class 并使用值填充 class 属性并将对象传递给函数。
这是使用 Cinchoo ETL 从 JSON 中选择节点的另一种方法 - 一个开源库
定义 POCO class 属性以及 JSON 路径
public class QueueItem
{
[ChoJSONPath("sWrapper.sid")]
public string SID { get; set; }
[ChoJSONPath("sWrapper.identifiers[0].value[0]")]
public string IdentifierValue { get; set; }
[ChoJSONPath("master.classification.identifier")]
public string ClassificationIdentifier { get; set; }
}
然后使用库反序列化JSON如下
using (var r = ChoJSONReader<QueueItem>.LoadText(json))
{
r.Print();
}
样本fiddle:https://dotnetfiddle.net/K7GnT8
正如其他人所提到的,您可以创建一个 class/classes 来表示您希望从服务总线消息中获取的信息。
public class ServiceBusMessage
{
[JsonPropertyName("sWrapper")]
public SWrapper SWrapper { get; set; }
[JsonPropertyName("classification")]
public Classification Classification { get; set; }
}
public class SWrapper
{
[JsonPropertyName("sid")]
public string Sid { get; set; }
[JsonPropertyName("identifiers")]
public SWrapperIdentifier[] Identifiers { get; set; }
}
public class SWrapperIdentifier
{
[JsonPropertyName("value")]
public string[] Value { get; set; }
}
public class Classification
{
[JsonPropertyName("identifier")]
public string Identifier { get; set; }
}
此外,如果您的 Azure Function 是 2.0 或更高版本,您可以将函数签名更改为:
public void Run([ServiceBusTrigger("product-data-dev-01", Connection = "ServiceBusConnectionString")] ServiceBusMessage myQueueItem, ILogger log)
框架将为您处理反序列化(根据 these 文档)。
然后您可以将这个“请求”对象映射到任何您想要使用的结构。