反序列化复杂类型但将选定的属性保持为序列化

Deserializing a complex type but keep selected properties as serialized

我正在将复杂的 json 对象反序列化为 POCO,然后使用 Microsoft.Azure.Cosmos.Table SDK 将数据存储到 Azure table 存储.但是,SDK 不支持插入复杂类型。我正在寻找一种反序列化我的 json 的方法,使复杂类型保持序列化,只有简单类型被反序列化。

这是我的 class 定义:

public class Person
{
   public string name {get; set;}
   public int department {get; set;}
   public List<Address> addresses {get; set;}
   public Skill skill {get; set;}
}

现在,我需要反序列化我的 json,这样 AddressesSkill 应该保留为 string,但其他属性应该被反序列化。这将允许我将整个对象存储到 Azure Table 存储中,并显示地址和技能的列。我知道 [JsonIgnore] 会简单地忽略我的 属性 这不是我需要的。

有什么办法可以做到吗?

这里的关键是使用不同的 class 来持久化,class 将从 JSON 反序列化,我们将其命名为 PersistablePerson.

我可以想到两种方法:

方法 1 - 使用自定义转换器

根据@dbc 建议的,创建自定义转换器:

public class RawConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return reader.TokenType != JsonToken.Null
            ? JRaw.Create(reader).ToString()
            : null;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue((string)value);
    }
}

可持久化 class 看起来像这样:

public class PersistablePerson
{
    public string name {get; set;}
    public int department {get; set;}

    [JsonConverter(typeof(RawConverter))] 
    public string addresses {get; set;}

    [JsonConverter(typeof(RawConverter))] 
    public string skill {get; set;}
}

方法 2 - 使用双倍属性

在持久性 class 中,将 "complex" 属性加倍,以便每个这样的 属性 由两个表示:

  • 一个字符串属性:包含在持久化中,被JSON序列化器忽略
  • a JToken 属性:由 JSON 序列化程序处理,从持久性中排除

JToken 属性 setter 和 getter 是读写字符串 属性.

的包装器
public class PersistablePerson
{
    public string name {get; set;}
    public int department {get; set;}

    [JsonIgnore] // exclude from JSON serialization, include in persistence
    public string addresses {get; set;}

    [IgnoreProperty]            // exclude from persistence
    [JsonProperty("addresses")] // include in JSON serilization
    public JToken addressesJson
    {
        get { return addresses != null ? JToken.Parse(addresses) : null; }
        set { addresses = value.ToString(); }
    }

    [JsonIgnore] // exclude from JSON serialization, include in persistence
    public string skill {get; set;}

    [IgnoreProperty]        // exclude from persistence
    [JsonProperty("skill")] // include in JSON serilization
    public JToken skillJson
    {
        get { return skill != null ? JToken.Parse(skill) : null; }
        set { skill = value.ToString(); }
    }
}