针对多消息的JSON反序列化设计模式C#



我有一个用例,其中一个.net应用程序在后台运行并侦听Kafka消息。我将收到来自Kafka的各种有效载荷/消息。每个有效载荷都有不同的结构,其中包含不同的项。对于每个有效载荷,我们必须将其反序列化为自己的实体(不总是一对一映射,在某些情况下,可以有一些有效载荷到实体的映射逻辑(,每个有效载荷在数据库中都有自己的表。因此,在反序列化之后,这些实体必须保存在数据库中,并发送到另一个Kafka主题。

大体上,我将整个流程分为三个部分来维护SRP。一个是反序列化,第二个是数据库保存,第三个是Kafka。

我目前正在实现反序列化,如下所示:

第一个有效载荷示例:

{
"type":"fuel",
"data":{
"fueltype":"petrol",
"mileage":23.76,
"tankcapacity":37
}
}
{
"type":"engine",
"data":{
"enginetype":"K series",
"maxpower":88.50,
"displacement":1197
}
}

因此,使用类型来区分这些消息

对于代码,我考虑为每种类型的使用单独的解析器

public interface IJsonParser
{
Payload Parse(dynamic data);
}
public class FuelParser : IJsonParser
{
public Payload Parse(dynamic payload)
{
Fuel f = new Fuel();
f.Mileage = (float)payload.data.mileage;
return f;
}
}
public class EngineParser : IJsonParser
{
public Payload Parse(dynamic data)
{
Engine e = new Engine();
return e;
}
}

public class Payload
{
public int Id { get; set; }
}
public class Fuel : Payload
{
public string FuelType { get; set; }
public float Mileage { get; set; }
public int TankCapacity { get; set; }
}
public class Engine : Payload
{
public string EngineType { get; set; }
public float MaxPower { get; set; }
public int Displacement { get; set; }
}


public static class JsonParserFactory
{
public static IJsonParser GetJsonParser(string type)
{
switch (type)
{
case "fuel":
return new FuelParser();
case "engine":
return new EngineParser();
default:
return null;
}
}
}
string message = "{rnt"type": "fuel",rnt"data":rntt{rnttt"fueltype": "petrol",rnttt"mileage": 23.76,rnttt"tankcapacity": 37rntt}rn}";
dynamic data = JsonConvert.DeserializeObject<object>(message);
IJsonParser parser = JsonParserFactory.GetJsonParser(data.type.ToString());
var model = parser.Parse(data);// This model will then be saved in DB as well as sent to another Kafka topic which is the 2nd and 3rd part of the flow.

因此,基于这种类型,我创建了一个Factory,它正在创建各个解析器。

如果这是一个好的设计,我只是想要这个建议。我唯一担心的是,未来会有多种类型的有效载荷,随着我们的发展,这些有效载荷会增加解析器的数量。

有什么建议吗?

也可以使用接受类型的DeserializeObject方法。这样,您就不需要编写任何特定于类型的解析器,只需要找到一个类型并将其提供给该方法即可。类似这样的东西:

public Payload GetPayload(string type, string message)
{
switch (type)
{
case "fuel":
return JsonConvert.DeserializeObject(message, typeof(Fuel));
case "engine":
return JsonConvert.DeserializeObject(message, typeof(Engine));
default:
return null;
}
}

然后,您可以用JsonProperties属性装饰实体类(基本上是映射(,如下所示(加上使用该覆盖器(:

[JsonConverter(typeof(JsonPathConverter))]
class Fuel : Payload
{
[JsonProperty("data.fueltype")]
public string FuelType{ get; set; }
[JsonProperty("data.mileage")]
public float Mileage { get; set; }
}

string message = "{rnt"type": "fuel",rnt"data":rntt{rnttt"fueltype": "petrol",rnttt"mileage": 23.76,rnttt"tankcapacity": 37rntt}rn}";
var type = GetMessageType(); // get type from message i.e. with JObject
var payload = GetPayload(type, message);

最新更新