.NET WebApi 如何防止 JSON 的 "$ref": "x" 输出

2024-01-23

我将 Web Api 与实体框架一起使用,我有一个名为 Gift 的控制器,当客户端 GET 的 API 时,我通过使用实体框架从 DB 获取所有 Gifts 并将其作为 JSON 返回

这是我的控制器功能

    public List<Gift> Get()
    {
        return GiftService.GetIncludeAndActive();
    }

这是服务功能

public List<Gift> GetIncludeAndActive()
{
    return dbSet.Include("GiftCategory").Where(x => x.Status == Model.Enums.GiftStatus.Active).OrderByDescending(x => x.Featured).ThenBy(x => x.Price).ToList();
}

这是礼物模型

public class Gift
    {
        public Gift()
        {
            this.CartItems = new List<CartItem>();
        }
        public int ID { get; set; }
        public string GiftName { get; set; }
        public string Image { get; set; }
        public int Stock { get; set; }
        public int Price { get; set; }
        public string Description { get; set; }
        public string Status { get; set; }
        public string GiftCode { get; set; }
        public int GiftCategoryID { get; set; }
        public Nullable<DateTime> CreatedAt { get; set; }
        public Nullable<DateTime> UpdatedAt { get; set; }
        public bool Featured { get; set; }
        public GiftCategory GiftCategory { get; set; }
        public ICollection<CartItem> CartItems { get; set; }

    }

[

这是 JSON 输出

{
        "$id": "1",
        "ID": 14,
        "GiftName": "Sinbo SVC-3438 1600 Watt Elektrikli Süpürge",
        "Image": "http://placehold.it/400x288.jpg/A6A",
        "Stock": 70,
        "Price": 260,
        "Description": "Az yer kaplayan Kompakt dizayn, Max. 1600W, 5m kablo uzunluğu, 360 derece dönüş açılı ön tekerlek, Dar ve ulaşılması zor yerler için 2 si 1 arada aparat ",
        "Status": "Active",
        "GiftCode": "BDRS-498",
        "GiftCategoryID": 4,
        "CreatedAt": "2016-12-19T12:59:01.31",
        "UpdatedAt": "2016-12-19T12:59:10.54",
        "Featured": false,
        "GiftCategory": {
          "$id": "2",
          "ID": 4,
          "Name": "Kişisel Bakım",
          "CountryID": 1,
          "Country": null,
          "Gifts": [
            {
              "$ref": "1"
            },
            {
              "$id": "3",
              "ID": 11,
              "GiftName": "Kişisel Bakım 2 - LG 43LH590V 43\"108 Ekran Full HD",
              "Image": "http://placehold.it/400x288.jpg/AEA",
              "Stock": 50,
              "Price": 3600,
              "Description": "Triple XD Engine teknolojisiyle güçlendirilen, Active Noise Reduction ve Real Cinema 24p özellikleriyle zenginleştirilen 1080p çözünürlüğündeki LED aydınlatmalı 55 inçlik ekrana sahip model, size ideal sinema keyfi sunuyor. Aynı zamanda sahip olduğu Color Prime, Dynamic Clear White ve Dynamic Colour Enhancer özellikleri sayesinde kusursuz bir görüntüyle evlerinizde yerini alıyor.",
              "Status": "Active",
              "GiftCode": "BDRS-495",
              "GiftCategoryID": 4,
              "CreatedAt": "2016-12-19T12:59:01.31",
              "UpdatedAt": "2016-12-19T12:59:10.54",
              "Featured": false,
              "GiftCategory": {
                "$ref": "2"
              },
              "CartItems": []
            },
            {
              "$id": "4",
              "ID": 8,
              "GiftName": "Kişisel Bakım 1 - Apple iPhone 6S 16 GB",
              "Image": "http://placehold.it/400x288.jpg/CCC",
              "Stock": 100,
              "Price": 5000,
              "Description": "Teknolojinin sunduğu tüm imkanlardan yararlanılarak tasarlanan Apple iPhone 6S , hem işlevsel hem de görsel açıdan ayrıcalıklı bir akıllı telefona sahip olmanıza olanak tanıyor.",
              "Status": "Active",
              "GiftCode": "BDRS-492",
              "GiftCategoryID": 4,
              "CreatedAt": "2016-12-19T12:59:01.31",
              "UpdatedAt": "2016-12-19T12:59:10.54",
              "Featured": false,
              "GiftCategory": {
                "$ref": "2"
              },
              "CartItems": []
            }
          ]
        },
        "CartItems": []
      },
      {
        "$id": "5",
        "ID": 13,
        "GiftName": "Beyaz Eşyalar 2 - Philips Marathon Ultimate FC9919/07 A Sınıfı Toz Torbasız Elektrikli Süpürge",
        "Image": "http://placehold.it/400x288.jpg/A1A",
        "Stock": 70,
        "Price": 900,
        "Description": "Yeni Philips Marathon Ultimate torbasız elektrikli süpürge, üstün temizlik performansı sunar. PowerCyclone 7, havayla tozu olağanüstü bir performansla ayırır. TriActiveMax başlık ise tüm zeminlerde mükemmel performans gösterir.",
        "Status": "Active",
        "GiftCode": "BDRS-497",
        "GiftCategoryID": 2,
        "CreatedAt": "2016-12-19T12:59:01.31",
        "UpdatedAt": "2016-12-19T12:59:10.54",
        "Featured": false,
        "GiftCategory": {
          "$id": "6",
          "ID": 2,
          "Name": "Beyaz Eşyalar",
          "CountryID": 1,
          "Country": null,
          "Gifts": [
            {
              "$ref": "5"
            },
            {
              "$id": "7",
              "ID": 6,
              "GiftName": "Beyaz Eşyalar 1 - Samsung Galaxy S7 Edge",
              "Image": "http://placehold.it/400x288.jpg/EEE",
              "Stock": 100,
              "Price": 6000,
              "Description": "Teknolojik yeniliklerin nereye kadar ulaşacağını kestiremeyen kullanıcılar, Samsung’un geliştirdiği ve bünyesinde barındırdığı yenilikçi özelliklerle öne çıkan telefonlarla şaşırmaya devam ediyor. Galaxy serisi içerisindeki en agresif atılımları üzerinde bulunduran Samsung Galaxy S7 Edge modelleri;alüminyum çerçeveleri, güçlü donanımları, benzersiz kameraları, suya ve toza karşı dayanıklılıkları ve sanal gerçeklik aygıtlarına doğrudan bağlanabilmeleriyle benzersiz hale geliyorlar.",
              "Status": "Active",
              "GiftCode": "BDRS-490",
              "GiftCategoryID": 2,
              "CreatedAt": "2016-12-19T12:59:01.31",
              "UpdatedAt": "2016-12-19T12:59:10.54",
              "Featured": false,
              "GiftCategory": {
                "$ref": "6"
              },
              "CartItems": []
            }
          ]
        },
        "CartItems": []
      },
      {
        "$id": "8",
        "ID": 7,
        "GiftName": "Elektronik 1 - Samsung Galaxy J7",
        "Image": "http://placehold.it/400x288.jpg/DDD",
        "Stock": 1000,
        "Price": 2500,
        "Description": "eknolojik yenilikleri yakından takip eden herkesin kullandığı akıllı cep telefonları, gelişmiş donanım ve yazılım özelliklerinin yanı sıra üzerlerinde bulunan kameralarla daha da kullanışlı hale geliyor. Dünya çapında milyonlarca kullanıcıya ulaşan ve akıllı cep telefonu sektörüne yön veren başlıca markalardan biri olan Samsung, Galaxy serisi içerisine konumlandırdığı Samsung Galaxy J7 modeliyle kendinden söz ettiriyor. ",
        "Status": "Active",
        "GiftCode": "BDRS-491",
        "GiftCategoryID": 3,
        "CreatedAt": "2016-12-19T12:59:01.31",
        "UpdatedAt": "2016-12-19T12:59:10.54",
        "Featured": false,
        "GiftCategory": {
          "$id": "9",
          "ID": 3,
          "Name": "Elektronik ",
          "CountryID": 1,
          "Country": null,
          "Gifts": [
            {
              "$ref": "8"
            },
            {
              "$id": "10",
              "ID": 12,
              "GiftName": "Elektronik  2 - Samsung 40JU6070 40\" 102 Ekran Ultra HD",
              "Image": "http://placehold.it/400x288.jpg/A6A",
              "Stock": 62,
              "Price": 3200,
              "Description": "TV standında kullanılabilen model, A enerji verimlilik sınıfında yer alıyor. Samsung 40JU6070 fiyatı kullanıcı açısından tercih edilir olmasında önemli bir rol oynuyor.4K teknolojisiyle yeni tanışacak olanların rahatlıkla yönelebilecekleri model, zengin giriş - çıkış noktalarıyla da cazip seçenekler arasında yer alıyor. Slim yapısı, pratik kullanımı ve gerek donanım gerekse yazılım anlamında Samsung’un elektronik alandaki deneyiminin bir eseri olarak nitelenebilecek akıllı televizyon, salon ya da oturma odalarınızın en sevilen eşyalarından biri oluyor.",
              "Status": "Active",
              "GiftCode": "BDRS-496",
              "GiftCategoryID": 3,
              "CreatedAt": "2016-12-19T12:59:01.31",
              "UpdatedAt": "2016-12-19T12:59:10.54",
              "Featured": false,
              "GiftCategory": {
                "$ref": "9"
              },
              "CartItems": []
            }
          ]
        },
        "CartItems": []
      },
      {
        "$id": "11",
        "ID": 9,
        "GiftName": "Küçük Ev Aletleri 1 - General Mobile 4G Android One",
        "Image": "http://placehold.it/400x288.jpg/BBB",
        "Stock": 150,
        "Price": 2600,
        "Description": "General Mobile 4G , diğer akıllı telefon modellerinden farklı olarak Google iş birliği ile geliştirilen Türkiye'deki ilk Android One cihaz olma özelliğine sahip ve bu yüzden benzeri bulunmayan eşsiz bir ürün.",
        "Status": "Active",
        "GiftCode": "BDRS-493",
        "GiftCategoryID": 5,
        "CreatedAt": "2016-12-19T12:59:01.31",
        "UpdatedAt": "2016-12-19T12:59:10.54",
        "Featured": false,
        "GiftCategory": {
          "$id": "12",
          "ID": 5,
          "Name": "Küçük Ev Aletleri",
          "CountryID": 1,
          "Country": null,
          "Gifts": [
            {
              "$ref": "11"
            }
          ]
        },
        "CartItems": []
      },
      {
        "$id": "13",
        "ID": 10,
        "GiftName": "Elektrikli Ev Aletleri 2 - Samsung 40J5070 40\" 102 Ekran Full HD",
        "Image": "http://placehold.it/400x288.jpg/AAA",
        "Stock": 50,
        "Price": 3000,
        "Description": "\r\nMarkaların ortaya koydukları televizyon modelleri, farklı donanım ve yazılım özellikleriyle öne çıkıyor. Gelişmiş 3D yetenekleri ve 4K çözünürlükleriyle sunulan bazı ürünler, sahip oldukları aygıttan çok sayıda özellik bekleyenlerin gereksinimlerini kolayca karşılıyor.",
        "Status": "Active",
        "GiftCode": "BDRS-494",
        "GiftCategoryID": 1,
        "CreatedAt": "2016-12-19T12:59:01.31",
        "UpdatedAt": "2016-12-19T12:59:10.54",
        "Featured": false,
        "GiftCategory": {
          "$id": "14",
          "ID": 1,
          "Name": "Elektrikli Ev Aletleri",
          "CountryID": 1,
          "Country": null,
          "Gifts": [
            {
              "$ref": "13"
            },
            {
              "$id": "15",
              "ID": 5,
              "GiftName": "Elektrikli Ev Aletleri 1 - Iphone 7 Plus 128GB",
              "Image": "http://placehold.it/400x288.jpg/FFF",
              "Stock": 200,
              "Price": 7500,
              "Description": "Apple markası iPhone serisi altında sunduğu cihazların arasına geçtiğimiz yıllarda Plus serisini de eklemişti. iPhone 7 cihazının yanı sıra sunulan iPhone 7 Plus , yüksek özellikleri ve normal iPhone’a göre büyük ekranı ile büyük ekran beklentisi olanların ihtiyacını karşılamayı hedefliyor.",
              "Status": "Active",
              "GiftCode": "BDRS-489",
              "GiftCategoryID": 1,
              "CreatedAt": "2016-12-19T12:59:01.31",
              "UpdatedAt": "2016-12-19T12:59:10.54",
              "Featured": false,
              "GiftCategory": {
                "$ref": "14"
              },
              "CartItems": []
            }
          ]
        },
        "CartItems": []
      },
      {
        "$ref": "10"
      },
      {
        "$ref": "3"
      },
      {
        "$ref": "4"
      },
      {
        "$ref": "7"
      },
      {
        "$ref": "15"
      }
    ]

正如你所看到的,有 "$ref":"13"、"$ref":"14" 等...我不想在 json 底部显示 $refs,我不想 $参考文献。我想要一个常规的 JSON 文件

这是我的 WebApiConfig.cs

     public static void Register(HttpConfiguration config)
        {

            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
            config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
.....

我可以用一种非常神秘的方法来解决这个问题;我在 web.config 文件中添加了一个新的空行并保存它,然后我再次调用 API,哇啦,它就如我所愿了。

但 1-2 小时后开始使用 $ref 发送数据,直到我向 web.config 文件添加一个新的空行。


Json.net 添加"$id" and "$ref"序列化 JSON 来处理循环引用。你的Gift对象包含GiftCategory其又包含列表Gift对象。

参考处理由以下控制:PreserveReferencesHandling串行器设置,但是设置SerializerSettings.PreserveReferencesHandling to PreserveReferencesHandling.None如果存在循环引用,则不适用于您,因为这会导致数据丢失。Json.net很聪明,不会让你射中自己的腿。

你可以尝试设置ReferenceLoopHandling to ReferenceLoopHandling.Ignore正如这篇伟大的文章中所描述的answer https://stackoverflow.com/a/23461179/5740031, 然而,由于序列化的特定顺序,Gift对象将在第一个引用位置被序列化。所以他们中的一些人会进入Gifts数组,其中一些会进入GiftCategory。看到这个question https://stackoverflow.com/questions/34675949/how-to-have-json-net-render-forward-references-during-serialization更多细节。

所以可能的修复方法是:

  1. 一开始按照建议here https://stackoverflow.com/a/14682268/5740031考虑不序列化 EF 实体。

  2. 如果导航属性GiftCategory.Gifts您的应用程序的业务逻辑实际上并不需要它,您可以从模型实体中将其删除。那么你将不再有循环引用,并且序列化的 JSON 将不再有"$ref" and "$id" fields.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

.NET WebApi 如何防止 JSON 的 "$ref": "x" 输出 的相关文章

随机推荐

  • Google Ads 链接器命令失败,退出代码为 1(使用 -v 查看调用)

    我最近从 iAd 切换到 Google Ads 它似乎在模拟器上运行良好 但每当我尝试在 iOS 设备上运行它时 我都会收到此错误 这有什么问题吗 我的项目发生了同样的错误 以下解决方案有效 请检查您的 xcode 项目中是否启用或禁用了位
  • 谷歌地图如何在最近的道路上强制标记

    我正在做一个车辆跟踪项目 我从数据库中获取坐标 并显示在谷歌地图上 这是我的代码 function get coordinates checkbox var v id checkbox id if checkbox checked var
  • 构建上下文无关语法

    如何为以下语言构建上下文无关语法 L a l b m c n d p l n m p l m n p gt 1 我首先尝试 S gt abcd aAbBcd abcCdD aAbcdD AabBcCd 进而A 其他东西 但我无法让它工作 我
  • 如何合并两个没有共同祖先的分支?

    我已经开始在项目中使用 Git 其中前两次提交只是一些初始设置 gitignore 和 gitattributes 第三次提交M2添加SVN trunk的内容 I1 I2 M2 N Z 我已将 SVN 历史记录导入名为svn where M
  • Sencha 命令上的 Cordova 和 PhoneGap 初始化失败

    我已经通过 NodeJS CLI 在 Ubuntu 13 10 上安装了 PhoneGap 并开始了本机构建过程 然而 在初始化期间 这是执行的命令和相应的输出 sencha phonegap init com foo barapp Bar
  • 使用 sed 将换行符转义 '\n' 替换为转义换行符转义 '\\n'

    我正在尝试替换字面术语 n 不是换行符 而是字面量 按字面量 n using sed 我试过这个 echo Refreshing n n n state prior sed s n n g 这 有效 但我需要它来输出文字字符 n 现在我最终
  • 在 Windows 上从命令行向 git commit -m 添加换行符

    我的公司有一项政策 即对特定项目的所有签入都必须遵循 git 提交的特定多行模板 如何最简单地从 Windows 命令行创建一条包含多行的提交消息 This is almost exactly a duplicate of Add line
  • 2个列表之间的共同元素比较

    给定两个输入列表 如何创建两个输入共有的元素列表 例如 对于输入 1 2 3 4 5 6 and 3 5 7 9 结果应该是 3 5 用于输入 this this n that and this not that that 结果应该是 th
  • XCode C++ 缺少精子()

    我正在使用 C 和 XCode 创建一个命令行应用程序来保存文件权限 但是我无法识别精子 方法 错误是 使用未声明的标识符 精子 我的包含内容和有问题的代码如下 My includes include
  • Android 4.3 上的 YouTube 嵌入式播放器

    我正在尝试将 YouTube 播放器嵌入到我的网页中 如下所示 我遇到的问题是 播放器最初加载并播放第一个视频正常 但是当调用 loadVideoById 时 播放器看起来要加载视频 视频标题文本更改 但随后卡在黑屏上而不是播放 自从我的手
  • 如何使用WinAPI隐藏控制台窗口?

    我试图隐藏控制台窗口当我的C使用这个简单的应用程序启动WinAPI code define CONSOLE NAME 6FD66E14 FF0F 4B94 B8AF AFE3D42DC399 void hide window void Se
  • 通过 cmake 从 C++ 扩展构建 Python 子模块

    我正在尝试通过 cmake 将 c 扩展作为子模块合并到现有的 python 库中 构建 C 扩展可以正常工作 并将其作为 python 模块导入也可以 但不能作为头库的子模块 我有以下目录结构 frontend foo py bar py
  • 如何从“git stash save --all”中恢复?

    我想隐藏未跟踪的文件 但我一直传递错误的选项 对我来说 这听起来是对的 git stash save a all 但这实际上也隐藏了被忽略的文件 正确的是 git stash save u include untracked 当我跑步时gi
  • Pandas-将值设置为空数据框

    我已经初始化了一个空的 pandas 数据框 现在正在尝试填充该数据框 但我一直遇到相同的错误 这是我正在使用的 简化的 代码 import pandas as pd cols list ABC df pd DataFrame column
  • 带有点击处理程序和滚动条的 Google 地图信息框

    我有一个使用 Google Maps javascript API 和 Infobox 插件 本机 InfoWindow 的可自定义版本 的应用程序 它工作得很好 直到我出现以下用例 如果内容很大 我需要一个带有滚动条的信息框 并且它还需要
  • 无法创建 ScriptPluginFactory 类型的服务

    我的 gradle 突然停止工作了 目前的配置是 环境变量为GRADLE HOME 指向Gradle 3 2 1 只需运行命令即可gradle在命令提示符下 我收到以下消息 What went wrong Could not create
  • 如何部署消息排序的pubsub触发云函数?

    我想部署一个带有消息排序的 Pubsub 触发的云函数 https cloud google com pubsub docs ordering https cloud google com pubsub docs ordering gclo
  • 我如何删除 python 2.7,因为我已经在 ubuntu 上安装了 3.6.5?

    我安装了 2 7 和 3 6 5 起初在 ubuntu 18 04 中 唯一可用的 python 版本是 3 6 但在我安装了 numpy 包之后 2 7 也安装了 它变成了默认版本 有什么解决方案可以使 3 6 成为默认值而不是 2 7
  • Zend Forms - 元素 ID 修改以允许重复使用

    我有一个Zend Form我想在一页中多次重复使用的对象 我遇到的问题是每次渲染时它都有相同的元素 ID 我一直无法找到一种方法 可以在每次渲染表单时为所有 ID 提供唯一的前缀或后缀 完整的解决方案 子类Zend Form class M
  • .NET WebApi 如何防止 JSON 的 "$ref": "x" 输出

    我将 Web Api 与实体框架一起使用 我有一个名为 Gift 的控制器 当客户端 GET 的 API 时 我通过使用实体框架从 DB 获取所有 Gifts 并将其作为 JSON 返回 这是我的控制器功能 public List