如何使用 system.text.json 创建类似于 Newtonsoft 的自定义转换器?
How can I create a custom converter similar to Newtonsoft using system.text.json?
我最近花了很多时间将旧的 asp.net 4.6 项目升级到 .Net 6。
我几乎一切正常,但我在使用 System.Text.Json
代替 Newtonsoft 时遇到问题。
在我的 Startup.cs 中,我很想像这样使用自定义转换器:
services.AddMvc()
.AddJsonOptions(opts => {
//custom converter for PlayerItemDto
opts.JsonSerializerOptions.Converters.Add(new PlayerItemConverter());
});
这是我尝试进行转换的地方。现在就是 Newtonsoft,我不确定这是否适用于 System.Text.Json
。
具体来说,我在 System.Text.Json
中找不到任何东西可以替代 var obj = JObject.Load(reader);
和 options.Populate(obj.CreateReader(), retval)
有人知道这是否可行吗?
这是我的转换器class:
public class PlayerItemConverter : CustomCreationConverter<PlayerItemDto>
{
public PlayerItemDto Create(String morality)
{
switch (morality) {
case "bad":
return new MonsterTypeDto();
case "good":
return new LeaderTypeDto();
}
}
public override Object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JObject.Load(reader);
var morality = (String) obj.Property("morality");
var retval = Create(morality);
serializer.Populate(obj.CreateReader(), retval);
return retval;
}
}
您的转换器需要派生自 JsonConverter,以及实现 CanConvert、Read 和 Write 例如:
public class PlayerItemConverter : JsonConverter<PlayerItemDto>
{
public override bool CanConvert(Type typeToConvert)
{
return typeof(PlayerItemDto).IsAssignableFrom(typeToConvert);
}
public override PlayerItemDto Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (JsonDocument jsonDoc = JsonDocument.ParseValue(ref reader))
{
// Convert your jsonDoc into a PlayerItemDto and return it
}
}
public override void Write(Utf8JsonWriter writer, PlayerItemDto value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value, options);
}
}
然后您可以注册您的转换器,或使用 class 上的属性声明它,例如:
[JsonConverter(typeof(PlayerItemConverter))]
public class PlayerItemDto
{
}
更新
考虑 classes:
public class PlayerItemDto
{
public string Name { get; set; }
public int Age { get; set; }
public AddressDto Address { get; set; }
}
public class AddressDto
{
public int HouseNumber { get; set; }
public string Street { get; set; }
}
您可以使用以下方式访问属性:
using (JsonDocument jsonDoc = JsonDocument.ParseValue(ref reader))
{
string name = jsonDoc.RootElement.GetProperty("Name").GetString();
int age = jsonDoc.RootElement.GetProperty("Age").GetInt32();
int houseNumber = jsonDoc.RootElement.GetProperty("Address").GetProperty("HouseNumber").GetInt32();
string street = jsonDoc.RootElement.GetProperty("Address").GetProperty("Street").GetString();
// Build your PlayerItemDto from the properties
}
我最近花了很多时间将旧的 asp.net 4.6 项目升级到 .Net 6。
我几乎一切正常,但我在使用 System.Text.Json
代替 Newtonsoft 时遇到问题。
在我的 Startup.cs 中,我很想像这样使用自定义转换器:
services.AddMvc()
.AddJsonOptions(opts => {
//custom converter for PlayerItemDto
opts.JsonSerializerOptions.Converters.Add(new PlayerItemConverter());
});
这是我尝试进行转换的地方。现在就是 Newtonsoft,我不确定这是否适用于 System.Text.Json
。
具体来说,我在 System.Text.Json
中找不到任何东西可以替代 var obj = JObject.Load(reader);
和 options.Populate(obj.CreateReader(), retval)
有人知道这是否可行吗?
这是我的转换器class:
public class PlayerItemConverter : CustomCreationConverter<PlayerItemDto>
{
public PlayerItemDto Create(String morality)
{
switch (morality) {
case "bad":
return new MonsterTypeDto();
case "good":
return new LeaderTypeDto();
}
}
public override Object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JObject.Load(reader);
var morality = (String) obj.Property("morality");
var retval = Create(morality);
serializer.Populate(obj.CreateReader(), retval);
return retval;
}
}
您的转换器需要派生自 JsonConverter,以及实现 CanConvert、Read 和 Write 例如:
public class PlayerItemConverter : JsonConverter<PlayerItemDto>
{
public override bool CanConvert(Type typeToConvert)
{
return typeof(PlayerItemDto).IsAssignableFrom(typeToConvert);
}
public override PlayerItemDto Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (JsonDocument jsonDoc = JsonDocument.ParseValue(ref reader))
{
// Convert your jsonDoc into a PlayerItemDto and return it
}
}
public override void Write(Utf8JsonWriter writer, PlayerItemDto value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value, options);
}
}
然后您可以注册您的转换器,或使用 class 上的属性声明它,例如:
[JsonConverter(typeof(PlayerItemConverter))]
public class PlayerItemDto
{
}
更新
考虑 classes:
public class PlayerItemDto
{
public string Name { get; set; }
public int Age { get; set; }
public AddressDto Address { get; set; }
}
public class AddressDto
{
public int HouseNumber { get; set; }
public string Street { get; set; }
}
您可以使用以下方式访问属性:
using (JsonDocument jsonDoc = JsonDocument.ParseValue(ref reader))
{
string name = jsonDoc.RootElement.GetProperty("Name").GetString();
int age = jsonDoc.RootElement.GetProperty("Age").GetInt32();
int houseNumber = jsonDoc.RootElement.GetProperty("Address").GetProperty("HouseNumber").GetInt32();
string street = jsonDoc.RootElement.GetProperty("Address").GetProperty("Street").GetString();
// Build your PlayerItemDto from the properties
}