【问题标题】:Prevent $id/$ref when serializing objects using Web API and JSON.NET使用 Web API 和 JSON.NET 序列化对象时防止 $id/$ref
【发布时间】:2014-01-29 13:50:55
【问题描述】:

我似乎无法阻止 Web API/JSON.NET 在序列化对象时使用 Newtonsoft.Json.PreserveReferencesHandling.Objects。换句话说,尽管使用了以下设置,但 $id/$ref 始终在序列化对象中使用:

public class MvcApplication : System.Web.HttpApplication {

    protected void Application_Start () {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    }

}

public static class WebApiConfig {

    public static void Register (HttpConfiguration config) {
        JsonMediaTypeFormatter jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().Single();
        jsonFormatter.UseDataContractJsonSerializer = false;
        jsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
        jsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
    }

}

有什么想法吗?

【问题讨论】:

  • WebApiConfig 类中设置这个(public static void Register (HttpConfiguration config) 从 Global.asax.cs 中的 protected void Application_Start () 调用
  • 根据下面@AndreHaverdings 的回答,将 PreserveReferencesHandling 设置为 All 会导致添加 id 和引用。将最后一行设置为 jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None; 应该可以解决问题。

标签: c# asp.net-mvc-4 json.net asp.net-web-api


【解决方案1】:

把它放在 Global.asax 中来配置引用处理。 PreserveReferencesHandling 不应为“全部”

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;

【讨论】:

  • 我尝试了所有 PreserveReferencesHandling 组合,包括“无”。每个设置(当前为“无”)都会产生相同的输出:$id/$ref 正在输出。某些东西,某处必须覆盖我的设置。
  • @Michael 你能解决这个错误吗?你能帮我解决这个问题吗:stackoverflow.com/questions/41244296/…
【解决方案2】:

如果在您的对象(例如 DataContract)上使用序列化属性,来自JSON.Net documentation on Serialization Attributes

除了使用内置的 Json.NET 属性外,Json.NET 还查找 [SerializableAttribute][2](如果 DefaultContractResolver 上的 IgnoreSerializableAttribute 设置为 false)[DataContractAttribute][3]、[DataMemberAttribute][ 4] 和 [NonSerializedAttribute][5] ... 在确定 JSON 如何被序列化和反序列化时。

它还说:

注意

Json.NET 属性优先于标准 .NET 序列化属性,例如如果属性上同时存在 JsonPropertyAttribute 和 DataMemberAttribute 并且都自定义了名称,则将使用 JsonPropertyAttribute 中的名称。

似乎问题的解决方案是将[JsonObject(IsReference = false)] 添加到您的对象中,如下所示:

[DataContract(IsReference = true)]
[JsonObject(IsReference = false)]
public class MyObject
{
    [DataMember]
    public int MyProperty { get; set; }
}

【讨论】:

    【解决方案3】:

    这是我用来在客户端处理 $id/$ref 对象的一些 javascript:

    // function to return a JSON object form a JSON.NET serialized object with $id/$ref key-values
    // obj: the obj of interest.
    // parentObj: the top level object containing all child objects as serialized by JSON.NET.
    function getJsonNetObject(obj, parentObj) {
        // check if obj has $id key.
        var objId = obj["$id"];
        if (typeof (objId) !== "undefined" && objId != null) {
            // $id key exists, so you have the actual object... return it
            return obj;
        }
        // $id did not exist, so check if $ref key exists.
        objId = obj["$ref"];
        if (typeof (objId) !== "undefined" && objId != null) {
            // $ref exists, we need to get the actual object by searching the parent object for $id
            return getJsonNetObjectById(parentObj, objId);
        }
        // $id and $ref did not exist... return null
        return null;
    }
    
    // function to return a JSON object by $id
    // parentObj: the top level object containing all child objects as serialized by JSON.NET.
    // id: the $id value of interest
    function getJsonNetObjectById(parentObj, id) {
        // check if $id key exists.
        var objId = parentObj["$id"];
        if (typeof (objId) !== "undefined" && objId != null && objId == id) {
            // $id key exists, and the id matches the id of interest, so you have the object... return it
            return parentObj;
        }
        for (var i in parentObj) {
            if (typeof (parentObj[i]) == "object" && parentObj[i] != null) {
                //going one step down in the object tree
                var result = getJsonNetObjectById(parentObj[i], id);
                if (result != null) {
                    // return found object
                    return result;
                }
            }
        }
        return null;
    }
    

    【讨论】:

    • 感谢您提供真正有效的答案。我花了半个小时试图在 Microsoft WebApi 2.1 中关闭它
    【解决方案4】:

    我的应用程序导致错误我调试了我的 asp.net 应用程序,直到它给了我导致此问题的模型集合。 只需放置 [JsonIgnore] 标记,它就可以正常工作。

    [JsonIgnore]
    public virtual ICollection<customer_details> customer_details { get; set; }
    

    您可以通过将 [JsonIgnore] 分配给 Model 中的所有 ICollection 来手动测试,以发现问题的根源。

    【讨论】:

      【解决方案5】:

      [JsonIgnore] 为我工作。在模型中,包括:

          [JsonIgnore] 
          public virtual ICollection<cell_order> cell_order { get; set; }
      

      很遗憾,这必须针对每个需要的情况进行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多