After trying almost any solution here on SO (this one is the lastest) I gave up and decided to ask for your help.
I'm trying to serialize/deserialize a collection of objects that extend a common abstract class. Serialization goes fine, but it fails when deserializing, throwing this exception:
'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.DLL
Could not create an instance of type Plugins.BaseModel. Type is an interface or abstract class and cannot be instantiated. Path 'Widgets[0].BackgroundColor', line 1, position 60.
Before goind into the code, here's the string that I'm trying to deserialize (I've indented the string to make it more readable!):
{
"Widgets": [
{
"$type": "SimpleBatteryModel",
"BackgroundColor": {
"A": 255,
"R": 229,
"G": 20,
"B": 0
},
"ForegroundColor": {
"A": 255,
"R": 255,
"G": 255,
"B": 255
},
"BackgroundOpacity": 1.0,
"WidgetPosition": {
"Left": 157.0,
"Top": 302.0,
"Right": 0.0,
"Bottom": 0.0
}
},
{
"$type": "DummyModel",
"Text": "Dummy Widget (4)",
"BackgroundColor": {
"A": 255,
"R": 229,
"G": 20,
"B": 0
},
"ForegroundColor": {
"A": 255,
"R": 255,
"G": 255,
"B": 255
},
"BackgroundOpacity": 1.0,
"WidgetPosition": {
"Left": 0.0,
"Top": 0.0,
"Right": 0.0,
"Bottom": 0.0
}
},
{
"$type": "SimpleBatteryModel",
"BackgroundColor": {
"A": 255,
"R": 229,
"G": 20,
"B": 0
},
"ForegroundColor": {
"A": 255,
"R": 255,
"G": 255,
"B": 255
},
"BackgroundOpacity": 1.0,
"WidgetPosition": {
"Left": 330.0,
"Top": 0.0,
"Right": 0.0,
"Bottom": 0.0
}
},
{
"$type": "DummyModel",
"Text": "Dummy Widget (4)",
"BackgroundColor": {
"A": 255,
"R": 229,
"G": 20,
"B": 0
},
"ForegroundColor": {
"A": 255,
"R": 255,
"G": 255,
"B": 255
},
"BackgroundOpacity": 1.0,
"WidgetPosition": {
"Left": 180.0,
"Top": 700.0,
"Right": 0.0,
"Bottom": 0.0
}
},
{
"$type": "SimpleBatteryModel",
"BackgroundColor": {
"A": 255,
"R": 229,
"G": 20,
"B": 0
},
"ForegroundColor": {
"A": 255,
"R": 255,
"G": 255,
"B": 255
},
"BackgroundOpacity": 1.0,
"WidgetPosition": {
"Left": 0.0,
"Top": 650.0,
"Right": 0.0,
"Bottom": 0.0
}
}
]
}
(Widgets
is an ObservableCollection<BaseModel>
)
While I'm not posting my JsonSerializerSettings
because I've got this error with any combination of settings, here's a little snippet of my code (focusing just on the serialized properties).
(class namespace Plugins.BaseModel
)
[JsonObject(MemberSerialization.OptIn)]
public abstract class BaseModel : ViewModelBase
{
...other stuff...
[JsonProperty]
public Color BackgroundColor
{
get { return _backgroundColor; }
set
{
if (_backgroundColor == value) return;
_backgroundColor = value;
RaisePropertyChanged(() => BackgroundColor);
}
}
[JsonProperty]
public Color ForegroundColor
{
get { return _foregroundColor; }
set
{
if (_foregroundColor == value) return;
_foregroundColor = value;
RaisePropertyChanged(() => ForegroundColor);
}
}
[JsonProperty]
public double BackgroundOpacity
{
get { return _backgroundOpacity; }
set
{
if (value == _backgroundOpacity) return;
_backgroundOpacity = value;
_backgroundColor.A = (byte) (_backgroundOpacity*255);
RaisePropertyChanged(() => BackgroundOpacity);
RaisePropertyChanged(() => BackgroundColor);
}
}
[JsonProperty]
public Thickness WidgetPosition
{
get { return _widgetPosition; }
set
{
if (value == _widgetPosition) return;
_widgetPosition = value;
RaisePropertyChanged(() => WidgetPosition);
}
}
...other stuff...
}
(class Plugins.widgets.PRIVATE.Dummy.DummyModel
)
[JsonObject(MemberSerialization.OptIn)]
public class DummyModel : BaseModel
{
... other stuff...
[JsonProperty]
public string Text
{
get { return _text; }
set
{
if (_text == value) return;
_text = value;
RaisePropertyChanged(() => Text);
}
}
... other stuff ...
}
(class Plugins.widgets.Battery.SimpleBattery.SimpleBatteryModel
)
[JsonObject(MemberSerialization.OptIn)]
public class SimpleBatteryModel : BaseModel
{
... other stuff ...
}
As you can see, both the concrete classes are inheriting properties from the base class, and those properties are serialized without errors. The problem comes when I try to deserialize, as the deserializer tries to create an instance of the base class instead of the derived one.
Does anyone have a solution to this problem?
EDIT: Since you're sking, here are my current settings (based on the answer linked at the start of the question)
_settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Binder = new TypeNameSerializationBinder("Plugins.{0}, Plugins")};
EDIT 2: Here's my project's structure:
Main Solution
\- Main App (WP app project)
\- MainPage.xaml
\- Model (WP C# library project)
\- MainViewModel.cs (contains the collection Widgets that I'm serializing)
\- Plugins (WP C# library project)
\- BaseModel.cs (the main abstract class)
\- widgets.PRIVATE.Dummy.DummyModel.cs (one of the concrete classes)
\- widgets.Battery.SimpleBattery.SimpleBatteryModel.cs (the other concrete class)
where Main App
references Model
which references Plugins