Десериализация сложного типа, но сохранение выбранных свойств как сериализованных - PullRequest
1 голос
/ 04 июля 2019

Я десериализирую сложный объект json в POCO, а затем использую Microsoft.Azure.Cosmos.Table SDK для хранения данных в хранилище таблиц Azure.Однако SDK не поддерживает вставку сложных типов.Я ищу способ десериализации моего json таким образом, чтобы сложные типы оставались сериализованными, а десериализовывались только простые типы.

Вот мое определение класса:

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 так, чтобы Адреса и Навык оставались в виде строки , но остальные свойства должны быть десериализованы.Это позволит мне сохранить весь мой объект в хранилище таблиц Azure с отображением столбцов для адресов и навыков.Я понимаю, что [JsonIgnore] просто проигнорирует мою собственность, а это не то, что мне нужно.

Есть ли способ, которым это можно сделать?

1 Ответ

1 голос
/ 04 июля 2019

Ключевым моментом здесь является использование другого класса для персистентности, класса, который будет десериализован из JSON, назовем его PersistablePerson.

Я могу придумать два подхода:

Подход1 - с помощью пользовательского конвертера

На основе другого ответа на SO , предложенного @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);
    }
}

Постоянный класс будет выглядеть следующим образом:

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 - использование удвоенных свойств

В постоянном классе удвойте "сложные" свойства, чтобы каждое такое свойство было представлено двумя:

  • строковое свойство: включено в постоянство, игнорируется сериализатором JSON
  • свойство JToken: обрабатывается сериализатором JSON, исключается из постоянства

Установка и получение свойства JTokenявляются обертками, которые читают и пишут строковое свойство.

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(); }
    }
}

...