Json.Net反序列化因派生类型的集合而失败

时间:2013-12-06 10:42:54

标签: c# json inheritance serialization json.net

在SO(this one is the lastest)尝试了几乎任何解决方案之后,我放弃了并决定寻求你的帮助。

我正在尝试序列化/反序列化扩展公共抽象类的对象集合。 序列化很顺利,但在反序列化时失败,抛出此异常:

  

Newtonsoft.Json.DLL中的'Newtonsoft.Json.JsonSerializationException'

     

无法创建Plugins.BaseModel类型的实例。 Type是接口或抽象类,无法实例化。 Path'Widgets [0] .BackgroundColor',第1行,第60位。

在进入代码之前,这是我正在尝试反序列化的字符串(我缩进字符串以使其更具可读性!):

{
  "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
      }
    }
  ]
}

WidgetsObservableCollection<BaseModel>

虽然我没有发布我的JsonSerializerSettings,因为我在任何设置组合中都遇到了这个错误,这里有一小段代码(仅关注序列化属性)。

(班级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...
}

(班级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 ...
}

(班级Plugins.widgets.Battery.SimpleBattery.SimpleBatteryModel

[JsonObject(MemberSerialization.OptIn)]
public class SimpleBatteryModel : BaseModel
{
    ... other stuff ...
}

正如您所看到的,具体类都是从基类继承属性,并且这些属性是序列化的,没有错误。 当我尝试反序列化时出现问题,因为反序列化器试图创建基类的实例而不是派生类的实例。

有没有人能解决这个问题?

编辑: 由于您正在尝试,这是我当前的设置(基于问题开头链接的答案)

_settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Binder = new TypeNameSerializationBinder("Plugins.{0}, Plugins")};

编辑2: 这是我项目的结构:

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)

其中Main App引用引用Model

Plugins

1 个答案:

答案 0 :(得分:1)

我没有看到您如何序列化和反序列化,但请确保您使用相同的JsonSerializerSettings进行反序列化。它不必是相同的实例,但它必须具有相同的选项才能进行反序列化。