问题描述
我需要执行以下操作,但是我需要在不将属性置于属性或污染模型类的情况下进行操作.理想的解决方案将通过JsonSerializerSettings
起作用,而不会干扰其他自定义序列化.顺便说一句,以下内容来自此问题: JSON.NET中的特定对象
I need to do something like the following, but I need to do it without putting an attribute on or otherwise polluting the model class. An ideal solution would work via the JsonSerializerSettings
, without disturbing other custom serialization. Incidentally, the below came from this question: Custom conversion of specific objects in JSON.NET
public class Person
{
public string FirstName { get; set; }
[JsonConverter(typeof(AllCapsConverter))]
public string LastName { get; set; }
// more properties here in the real example, some of which nest to properties that use their own JsonConverters.
}
此玩具示例的JsonConverter
(内容并非真正相关;相关的是我将其用于属性):
The JsonConverter
for this toy example (content is not really relevant; what is relevant is that I use it for the property):
public class AllCapsConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
=> objectType == typeof(string);
public override bool CanRead => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotSupportedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var str = value as string;
var upper = str.ToUpperInvariant();
JToken j = JToken.FromObject(upper);
j.WriteTo(writer);
}
}
通过单元测试:
public class PersonSerializationTest
{
[Fact]
public void SerializePerson_LastNameCaps()
{
var person = new Person
{
FirstName = "George",
LastName = "Washington"
};
var serialized = JsonConvert.SerializeObject(person);
var expected = @"{""FirstName"":""George"",""LastName"":""WASHINGTON""}";
Assert.Equal(expected, serialized);
}
}
推荐答案
您可以以编程方式将JsonConverter
应用于模型类中的一个或多个属性,而无需通过自定义ContractResolver
使用属性.这是一个简单的示例,将您的AllCapsConverter
应用于Person
类中的LastName
属性. (如果您正在寻找更强大的解决方案,请查看@dbc的答案.我的目的是展示最简单的可能可行的示例.)
You can programmatically apply a JsonConverter
to one or more properties in a model class without using attributes via a custom ContractResolver
. Here is a dirt simple example, which applies your AllCapsConverter
to the LastName
property in your Person
class. (If you're looking for a more robust solution, have a look at @dbc's answer. My intent here was to show the simplest example that could possibly work.)
public class CustomResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
if (prop.DeclaringType == typeof(Person) && prop.UnderlyingName == "LastName")
{
prop.Converter = new AllCapsConverter();
}
return prop;
}
}
这是更新的测试和Person
模型,其中显示了如何使用解析器:
Here is the updated test and Person
model which shows how to use the resolver:
public class PersonSerializationTest
{
[Fact]
public void SerializePerson_LastNameCaps()
{
var person = new Person
{
FirstName = "George",
LastName = "Washington"
};
var settings = new JsonSerializerSettings
{
ContractResolver = new CustomResolver()
};
var serialized = JsonConvert.SerializeObject(person, settings);
var expected = @"{""FirstName"":""George"",""LastName"":""WASHINGTON""}";
Assert.Equal(expected, serialized);
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
正在运行的演示: https://dotnetfiddle.net/o4e3WP
这篇关于在Json.NET中仅针对一个属性的自定义序列化程序,而无需更改模型类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!