一尘不染

使属性反序列化但不使用json.net序列化

c#

我们有一些配置文件,这些文件是通过使用Json.net序列化C#对象而生成的。

我们希望将序列化类的一个属性从简单的枚举属性迁移到类属性。

一种简单的方法是将旧的enum属性保留在类中,并安排Json.net在加载配置时读取此属性,但在下次序列化对象时不再保存它。我们将处理从旧枚举分别生成新类的问题。

有没有简单的方法来标记(例如,带有属性)C#对象的属性,以便Json.net仅在序列化时将其忽略,而在反序列化时将对其进行关注?


阅读 196

收藏
2020-05-19

共1个答案

一尘不染

实际上,可以使用几种相当简单的方法来获得所需的结果。

例如,假设您当前定义了这样的类:

class Config
{
    public Fizz ObsoleteSetting { get; set; }
    public Bang ReplacementSetting { get; set; }
}

enum Fizz { Alpha, Beta, Gamma }

class Bang
{
    public string Value { get; set; }
}

而您想这样做:

string json = @"{ ""ObsoleteSetting"" : ""Gamma"" }";

// deserialize
Config config = JsonConvert.DeserializeObject<Config>(json);

// migrate
config.ReplacementSetting = 
    new Bang { Value = config.ObsoleteSetting.ToString() };

// serialize
json = JsonConvert.SerializeObject(config);
Console.WriteLine(json);

为了得到这个:

{"ReplacementSetting":{"Value":"Gamma"}}

方法1:添加ShouldSerialize方法

Json.NET可以通过ShouldSerialize在类中查找相应的方法来有条件地序列化属性。

若要使用此功能,请ShouldSerializeBlah()在您的类中添加一个布尔方法,该方法将Blah替换为您不想序列化的属性的名称。使此方法的执行始终返回false

class Config
{
    public Fizz ObsoleteSetting { get; set; }

    public Bang ReplacementSetting { get; set; }

    public bool ShouldSerializeObsoleteSetting()
    {
        return false;
    }
}

注意:如果您喜欢这种方法,但又不想通过引入一种ShouldSerialize方法弄混类的公共接口,则可以使用an
IContractResolver来以编程方式执行相同的操作。请参阅文档中的条件属性序列化

方法2:使用JObjects处理JSON

无需使用JsonConvert.SerializeObject序列化方法,JObject只需将config对象加载到中,然后在将其写出之前从JSON中删除不需要的属性即可。这只是几行额外的代码。

JObject jo = JObject.FromObject(config);

// remove the "ObsoleteSetting" JProperty from its parent
jo["ObsoleteSetting"].Parent.Remove();

json = jo.ToString();

方法3:巧妙(滥用)属性使用

  1. [JsonIgnore]属性应用于您不想序列化的属性。
  2. 向该类添加一个替代的 私有 属性设置器,其类型与原始属性相同。使该属性的实现设置为原始属性。
  3. [JsonProperty]属性应用于替代设置器,为其赋予与原始属性相同的JSON名称。

这是修改后的Config类:

class Config
{
    [JsonIgnore]
    public Fizz ObsoleteSetting { get; set; }

    [JsonProperty("ObsoleteSetting")]
    private Fizz ObsoleteSettingAlternateSetter
    {
        // get is intentionally omitted here
        set { ObsoleteSetting = value; }
    }

    public Bang ReplacementSetting { get; set; }
}
2020-05-19