如何在angular2 +中序列化/反序列化.NET类型的JSON

时间:2018-05-17 15:52:24

标签: c# .net json angular deserialization

我从 Angular客户端调用 .NET Web Api ,并使用 JSON 来序列化/反序列化数据。

我正在尝试反序列化包含 Detector 列表的 Model 对象。 Detector是一个抽象类,有两个继承的子类: TextDetector ColorDetector

为了能够识别在反序列化期间需要实例化哪种类型的Detector,我将 TypeNameHandling.Auto 设置为我的JsonSerializerSettings(.NET端)。

包含TextDetector的模型的典型获取响应

{
  "Detectors": {
    "$type": "System.Collections.Generic.HashSet`1[[I2D_Api.Models.Detector, I2D Api]], System.Core",
    "$values": [
      {
        "$type": "I2D_Api.Models.TextDetector, I2D Api",
        "Id": 1,
        "Name": "Detector0",
        "Bounds": "0, 0, 0, 0"
      }
    ]
  },
  "Id": 1,
  "Name": "Modèle 0",
  "ImgModelLink": "https://gamewave.fr/static/images/medias/upload/Fortnite/canards/Fortnite_20180515121231.jpg"
}

但我不喜欢这个解决方案(我甚至无法工作),因为这表明我必须在每个客户端请求(Post或Put)上手动输入我的数据才能正确反序列化.NET端...除此之外,我还没有成功将这个JSON反序列化为一个Model对象客户端,因为 $ prefixes (但我认为这是不可思议的)

我想我走错了路,我已经搜索但找不到另一种传递这个集合的方法,这似乎是肮脏的。还有另一种方法吗?

注意:我正在使用EntityFramework,这是我的get方法

[ResponseType(typeof(Model))]
public IHttpActionResult GetModel(int id)
{
    Model model = db.Models.Find(id);
    if (model == null)
    {
        return NotFound();
    }

    return Ok(model);
}

编辑:所以我按照@dbc链接:Deserializing polymorphic json classes without type information这完全是我想要的。我实现了一个Json转换器,它根据缺失的属性 Color (没有color属性= TextDetector,color属性= ColorDetector)来知道子类的实例。

还通过Detector类中的X,Y,Width和Height属性替换了我的Bounds属性( JsonProperty.ValueProvider 无法在struct上提取值)(不是问题)。最后将 TypeNameHandling 更改为 Object

但是现在我遇到了一个我不明白的stackoverflow异常。请注意 TextDetector 没有检测器的属性/属性 错误来自我的 DetectorConverter

中的这一行
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    JObject item = JObject.Load(reader); // This throw stackoverflow exception
    if (item["Color"] == null)
    {
        return item.ToObject<TextDetector>();
    }
    else
    {
        return item.ToObject<ColorDetector>();
    }
}

在第一次 ReadJson 执行时,没有异常。但是,它看起来像 JObject.load(reader)导致内部循环,我无法在堆栈中看到它因为它是外部代码。我所知道的是,从读者加载后的项目类型是第一次执行时 Detector ,然后 TextDetector ,永远循环..

1 个答案:

答案 0 :(得分:0)

感谢@dbc指出我正确的方向。

  

Deserializing polymorphic json classes without type information using json.net

此链接的接受答案是正确的答案。

我想补充一些精确度:

  • 使用这个解决方案,我不得不删除抽象类的 struct 属性,因为转换无法读取它们(我认为这是可能的,但我更喜欢将struct的属性提取到我的abtrast类中)
  • 在读取传入的Json时,您可能会遇到 stackoverflow异常。您可以使用serializer.populate替换JObject toItem方法来解决此问题。或者,这就是我所做的,应用JSON NoConverter来混合子类

NoConverter类,您可以复制/粘贴并将其用作属性,就像其他所有JsonConverter一样

public class NoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return false;
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}