c# - 如何在 Angular 2 中序列化/反序列化 .NET 类型的 JSON

标签 c# .net json angular deserialization

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

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

为了能够识别在反序列化期间需要实例化哪种类型的检测器,我将 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 反序列化为模型对象客户端(但我猜这是可行的)

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


注意:我正在使用 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(没有颜色属性 = TextDetector,颜色属性 = ColorDetector)来实例化子类。

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

但是现在我遇到了一个我不明白的 stackoverflow 异常。请注意,TextDetector 没有比 Detector 更多的属性/特性 错误来 self 的 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,永远循环..

最佳答案

感谢@dbc 为我指明了正确的方向。

Deserializing polymorphic json classes without type information using json.net

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


我想补充一些精确度:

  • 使用此解决方案,我不得不删除抽象类的 struct 属性,因为 convert 无法读取它们(我认为这是可能的,但我更愿意将 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();
    }
}

关于c# - 如何在 Angular 2 中序列化/反序列化 .NET 类型的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50395743/

相关文章:

c# - 防止用户通过系统热键退出 Windows 应用程序

ruby-on-rails - 事件模型序列化不适用于 api 版本控制

c# - 如何向 Windows 窗体面板动态添加标签或其他元素?

.net - 如何实现多行文本框的花式滚动条?

c# - 如何从 EF Core/.NET Core 2.0 中的实体名称获取 DbSet

c++ - 具有大消息的跨平台 RPC

javascript - 如何使用rollupjs删除d3选择中的循环依赖?

java - 解码java google oauth2.0 JWT

c# - 当 JSON 字典为空时,反序列化 JSON 字符串失败

c# - 如何为一组对象生成独立于顺序的唯一哈希