2

I'm deserializing a complex json object to POCO and then using the Microsoft.Azure.Cosmos.Table SDK for storing data to Azure table storage. However, the SDK doesn't support inserting complex types. I'm looking for a way to desrialize my json in such a way that the complex types remain serialized and only simple types are deserialized.

Here's my class definition:

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

Now, I need to deserialize my json such that Addresses and Skill should stay as a string, but the other properties should get deserialized. This will allow me to store my entire object to Azure Table storage, with columns showing up for addresses and skill. I understand that [JsonIgnore] will simply ignore my property which is not what I need.

Is there any way this can be done?

IronMan
  • 309
  • 4
  • 22
  • Would `RawConverter` from [How can I serialize and deserialize a type with a string member that contains “raw” JSON, without escaping the JSON in the process](https://stackoverflow.com/q/40529125/3744182) meet your needs? You would modify your complex properties to strings and apply the converter, i.e. `[JsonConverter(typeof(RawConverter))] public string Address { get; set; }`. – dbc Jul 04 '19 at 06:02

1 Answers1

2

The key here is use a different class for persistence, the class that will be deserialized from JSON, let's name it PersistablePerson.

I can think of two approaches:

Approach 1 - using custom converter

Based on another answer on SO suggested by @dbc, create a custom converter:

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

The persistable class would look like this:

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

Approach 2 - using doubled properties

In the persistable class, double the "complex" properties so that every such property is represented by two:

  • a string property: included in persistence, ignored by JSON serializer
  • a JToken property: handled by JSON serializer, excluded from persistence

The JToken property setter and getter are wrappers that read and write the string property.

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

felix-b
  • 8,178
  • 1
  • 26
  • 36