3

I am trying to deserialize some json into some simple objects that inherit from Reactive UI's ReactiveObject class. For some reason the properties will never get filled there. Using a POCO instead works without any problems.

class Program
{
    class Profile
    {
        public string Name { get; set; }
    }

    class ReactiveProfile : ReactiveObject
    {
        private string _name;

        public string Name
        {
            get => _name;
            set => this.RaiseAndSetIfChanged(ref _name, value);
        }
    }

    static void Main(string[] args)
    {
        var profiles = new List<Profile>()
        {
            new Profile() {Name = "Foo"},
            new Profile() {Name = "Bar"}
        };

        var path = @"C:\temp\profiles.json";

        File.WriteAllText(path,
            JsonConvert.SerializeObject(profiles.ToArray(),
                Formatting.Indented,
                new StringEnumConverter()),
            Encoding.UTF8);

        // works
        var pocoProfiles = (Profile[])JsonConvert.DeserializeObject(
            File.ReadAllText(path, Encoding.UTF8),
            typeof(Profile[]));

        // properties not filled
        var reactiveProfiles = (ReactiveProfile[])JsonConvert.DeserializeObject(
            File.ReadAllText(path, Encoding.UTF8),
            typeof(ReactiveProfile[]));

        if (File.Exists(path))
        {
            File.Delete(path);
        }
    }
}
metacircle
  • 2,438
  • 4
  • 25
  • 39

1 Answers1

5

To properly serialize ReactiveObjects you should use the DataContract attribute of the System.Runtime.Serialization namespace. Then mark the members you'd like to save with the DataMember attribute, and the ones you don't want to save with the IgnoreDataMember attribute.

So in your case, something like this:

[DataContract]
class ReactiveProfile : ReactiveObject
{
    [IgnoreDataMember]
    private string _name;

    [DataMember]
    public string Name
    {
        get => _name;
        set => this.RaiseAndSetIfChanged(ref _name, value);
    }
}

Here's one of Paul's old example usages on Github: link

And a documentation link for data persistence: link

I ran the code you provided with this change, and it works as expected. Let me know if you have any questions.

Colt Bauman
  • 564
  • 3
  • 9
  • 1
    Works perfectly! Can you explain why I have to do this explicitly? Because when I change the Name property on the Poco Profile class to use a backing field it still works there without the attributes. – metacircle Jul 04 '18 at 13:05
  • 3
    @metacircle in short, it's because ReactiveObject has the _DataContract_ attribute. So any property in a derived class not decorated with a _DataMember_ attribute will not be serialized (at least using JSON.net; other serialization libraries may not have this side effect). Check [this answer](https://stackoverflow.com/a/29203876/5984310) out for more info. And if you're curious about these attributes, here's a [nice, quick overview](https://stackoverflow.com/a/4836803/5984310). – Colt Bauman Jul 04 '18 at 14:20