【问题标题】:How does JSON.NET serialize objects when using EF table-per-hierarchy?JSON.NET 在使用 EF table-per-hierarchy 时如何序列化对象?
【发布时间】:2013-04-25 22:28:02
【问题描述】:

我在我的 ASP.NET Web API 项目中使用 Entity Framework Code First table-per-hierarchy。我的一个模型有一个 List 是层次结构的抽象基类的类型。

List<Dog> // (for example; with GoldenRetriever, BorderCollie, etc inheriting)

我正在尝试使用 Fiddler 测试将一些数据发布到我的 API 控制器。但是当我这样做时,我不知道如何表示 JSON。如果我尝试类似:

"Dogs":
[
    {"Name":"Bud", "Age":"3"}
]

我得到错误:

"无法创建 Models.Dog 类型的实例。类型是一个接口 或抽象类,无法实例化。”

在 JSON 中指定鉴别器对我也没有帮助。有人有想法么?谢谢!

编辑:解决方案

诀窍是在 JSON 字符串中使用 $type 属性。有关更多信息,请参阅 m.t.bennett 在 cmets 中建议的 this link

要启用 $type 属性,我需要将以下内容添加到 WebApiConfig.cs:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling 
    = TypeNameHandling.Auto;

然后在将 JSON 发布到 Fiddler 时,我添加了带有完整对象路径的 $type 属性:

{"$type":"Example.Models.Dogs.GoldenRetriever, Example.Models",
    "Name":"Bud","Age":3}

为了弄清楚这种格式,我使用了 Snixtor 的建议来序列化对象并输出 JSON 字符串。太棒了!

我不确定这是否是最优雅的解决方案,因为它是 JSON.NET specific,但它确实有效!

【问题讨论】:

  • 我发现确定模型的 JSON 格式的最佳方法是将现有实例序列化为 JSON。你试过吗?
  • @Snixtor 很好的建议(将来会使用它),但没有帮助。我使用 JsonConvert 来序列化列表,它基本上吐出了我已经尝试过的内容。没有证据表明有任何方法可以区分对象类型。
  • 这个链接stackoverflow.com/questions/6348215/… 有帮助吗?
  • @m.t.bennett 这确实有帮助!使用您的建议和 Snixtor 的建议,我们解决了这个谜题。我会尽快用解决方案更新我的答案。

标签: asp.net entity-framework asp.net-web-api


【解决方案1】:

我使用了一个自定义的 JsonConverter 来处理基本类型的反序列化。

    public override bool CanConvert(Type objectType) {
        return typeof(Mybase).Equals(objectType);
    }

    public override MyBase Deserialize(JsonReader reader, MyBase existingValue, JsonSerializer serializer) {
        var ret = existingValue;
        var jobj = JObject.ReadFrom(reader);
        if (jobj["type"] == null || jobj["type"].Type != JTokenType.String)
            throw new JsonSerializationException("Supplied JSON is missing the required 'type' member.");

        var typeName = jobj["type"].Value<string>();

        var t = this.GetType().Assembly.GetType("MyNamespace." + typeName);
        if(t == null)
            throw new JsonSerializationException(String.Format("Could not identify supplied type '{0}' as a known type.", typeName));

        if (existingValue != null && !t.IsInstanceOfType(existingValue))
            throw new JsonSerializationException(String.Format("Type Mismatch: existingValue {0} is not assignable from supplied Type {1}", existingValue.GetType().Name, t.Name));

        ret = (ContactMethod)jobj.ToObject(t);

        return ret;
    }

并在应用初始化时注册了JsonConverter:

JsonSerializerSettings settings;
settings.Converters.Add(new MyBaseConverter());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    相关资源
    最近更新 更多