本文介绍了在Json.NET中仅针对一个属性的自定义序列化程序,而无需更改模型类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要执行以下操作,但是我需要在不将属性置于属性或污染模型类的情况下进行操作.理想的解决方案将通过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中仅针对一个属性的自定义序列化程序,而无需更改模型类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:08