2

I have a project with about 200 classes which need to be saved as json and deserialized back later. All the classes are immutable and due to this fact I need to inject all complex types into the constructor, otherwise deserialization does not work. Because I use a Clonable base class I don't initialize every parameter in the constructor. When I forget to add a single class to the construtor or misspell it, deserialization does not work anymore and the only way I know to check is to write a lot of unit tests with sample data.

This is a sample to reproduce my problem:

static void Main(string[] args)
{
    var immutableClass = new ImmutableClass(new OtherImmutableClass(2)).WithAnyProperty(1);
    var jsonString = JsonConvert.SerializeObject(immutableClass, Formatting.Indented);
    var deserializedObject = JsonConvert.DeserializeObject<ImmutableClass>(jsonString);
}

public class ImmutableClass : Clonable<ImmutableClass>
{
    public ImmutableClass(OtherImmutableClass otherImmutableClassInstance)
    {
        OtherImmutableClassInstance = otherImmutableClassInstance;
    }

    public OtherImmutableClass OtherImmutableClassInstance { get; }

    [JsonProperty]
    public int AnyProperty { get; private set; }

    public ImmutableClass WithAnyProperty(int newValue)
    {
        return With(s => s.AnyProperty = newValue);
    }
}

public class OtherImmutableClass
{
    public OtherImmutableClass(int completelyWrongPropertyName)
    {
        MyProperty = completelyWrongPropertyName;
    }

    public int MyProperty { get; }
}

public abstract class Clonable<T> where T : Clonable<T>
{
    protected T With(Action<T> updateAction)
    {
        var clone = (T)MemberwiseClone();
        updateAction(clone);
        return clone;
    }
}

After serialization the content of my jsonString is as expected:

{
  "OtherImmutableClassInstance": {
    "MyProperty": 2
  },
  "AnyProperty": 1
}

When I deserialize no Exception is thrown but the MyProperty is 0 instead of 2 because of completelyWrongPropertyName does not match MyProperty in the constructor of OtherImmutableClass.

Is there an easy way to check if my model is serializable and deserializable without writing UnitTests for each class?

I am searching something like JsonChecker<ImmutableClass>.CanSerializeAndDeserialize();

I already asked google but found no solution.

dbc
  • 104,963
  • 20
  • 228
  • 340
PTronics
  • 21
  • 4
  • What does serializability have to do with whether you misspelled something? – Heretic Monkey Oct 27 '20 at 15:58
  • BTW, your code on DotNetFiddle: https://dotnetfiddle.net/HAsobi – Heretic Monkey Oct 27 '20 at 16:04
  • Isn't your main problem with `OtherImmutableClass` the fact that you don't have a parameterless constructor, or haven't marked the constructor you do have with `[JsonConstructor]` so the deserializer knows to use it? I don't think "misspelling" has anything to do with it. – Sean Skelly Oct 27 '20 at 22:53
  • Anyway, I doubt there is any easy way to get what you want. It's up to you to define whether serialization/deserialization 'worked' or not for your classes, because it's you who created them. Unit testing is likely the best way to define success for yourself. – Sean Skelly Oct 27 '20 at 22:53
  • Testing whether a class "is serializable" by Json.NET is kind of vague an open-ended. (Just seeing whether Json.NET can construct the object is nontrivial; see [here](https://stackoverflow.com/a/41871975/3744182)) for the algorithm.) However, if you just want to ensure every constructor parameter has an equivalent property, then that's straightforward. See [How to throw an exception when JsonConstructor parameter name doesn't match JSON?](https://stackoverflow.com/q/63898984/3744182) for how. – dbc Oct 27 '20 at 23:49

0 Answers0