ServiceStack.Text序列化循环引用

2024-04-04

我需要像这样序列化对象图:

public class A
{
     public B Link1 {get;set;}
}

public class B
{
     public A Link2 {get;set;}
}

这样json只得到两个实例,但又被正确反序列化了。例如。使用元 ID 或类似的东西。

我知道 Json.NET 有一种方法,如下所述:http://note.harajuku-tech.org/serializing-circular-references-with-jsonnet http://note.harajuku-tech.org/serializing-circular-references-with-jsonnet带有元 ID。

是否有类似的功能ServiceStack.TextJson 序列化器?

否则,是否可以使用 Json.NETServiceStack如何?

EDIT:

为了清楚起见,我要求提供实例参考,而不仅仅是相同类型。 这方面的一个例子可能是:

[
    {
        "$id": "1",
        "BroId": 0,
        "Name": "John",
        "Bros": [
            {
                "$id": "2",
                "BroId": 0,
                "Name": "Jared",
                "Bros": [
                    {
                        "$ref": "1"
                    }
                ]
            }
        ]
    },
    {
        "$ref": "2"
    }
]

只有 2 个对象“真正”序列化,其余的通过使用$ref财产领域。 想象一个具有子项集合的对象模型。这些子项具有对其父对象的反向引用。例如。客户订单。一个客户有多个订单,每个订单都有对其客户的引用。 现在想想如果您序列化一位客户会发生什么。

Customer
 -> Order
  -> Customer
   -> Order
    -> ...

您会得到类似于该网站名称的结果。 ;)

我真的很喜欢 ServiceStack,因为它的清晰性,而不是要求KnownTypeAttributes etc.

我希望保持它的干净,而不是在我的业务逻辑 pocos 中实现自定义加载器/对象初始化程序。


我通过另一种方式解决了这个问题。这实际上是有效的,但是当使用具有多个循环引用的更复杂的数据结构时,它可能会在以后出现问题。但目前还没有必要。

我尝试添加循环引用功能ServiceStack.Text但发现没有任何开始的意义。也许mythz可以给我一个提示?该功能应该非常容易完成。

我需要该功能来序列化我的数据模型以完全支持NHibernate的合并函数。

我按照神话的建议忽略了属性IgnoreDataMemberAttribute这会导致循环引用。 但这也需要在反序列化后再次重建它们,以使合并功能正常工作。

-> 这就是解决方案,现在按照我的做法进行操作:

我从一个简单的原型开始进行测试,这是一个数据模型

Customer 1->n Orders 1->n OrderDetail.

每个类都派生自实体类。

public class Customer : Entity
{
    public virtual string Name { get; set; }
    public virtual string City { get; set; }
    public virtual IList<Order> Orders { get; set; }
}

public class Order : Entity
{
    public virtual DateTime OrderDate { get; set; }
    public virtual IList<OrderDetail> OrderDetails { get; set; }
    [IgnoreDataMember]
    public virtual Customer Customer { get; set; }
}

public class OrderDetail : Entity
{
    public virtual string ProductName { get; set; }
    public virtual int Amount { get; set; }
    [IgnoreDataMember]
    public virtual Order Order{ get; set; }
}

如你看到的,Order and OrderDetail有对其父对象的反向引用,这会在序列化时导致循环引用。这可以通过忽略反向引用来解决IgnoreDataMemberAttribute.

我现在的假设是,每个子实例Order这是里面的Customer的列表属性Orders有对此的反向引用Customer实例。

这就是我重建循环树的方法:

public static class SerializationExtensions
{
    public static void UpdateChildReferences(this object input)
    {
        var hashDictionary = new Dictionary<int, object>();
        hashDictionary.Add(input.GetHashCode(), input);

        var props = input.GetType().GetProperties();
        foreach (var propertyInfo in props)
        {
            if (propertyInfo.PropertyType.GetInterfaces()
                .Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
            {

                var instanceTypesInList = propertyInfo.PropertyType.GetGenericArguments();
                if(instanceTypesInList.Length != 1)
                    continue;

                if (instanceTypesInList[0].IsSubclassOf(typeof(Entity)))
                {
                    var list = (IList)propertyInfo.GetValue(input, null);
                    foreach (object t in list)
                    {
                        UpdateReferenceToParent(input, t);
                        UpdateChildReferences(t);
                    }
                }
            }
        }
    }

    private static void UpdateReferenceToParent(object parent, object item)
    {
        var props = item.GetType().GetProperties();
        var result = props.FirstOrDefault(x => x.PropertyType == parent.GetType());

        if (result != null)
            result.SetValue(item, parent, null);
    }
}

此代码不适用于1->1目前实体引用(还不需要),但我认为它可以很容易地扩展。

现在,我可以在客户端拥有 POCO 类模型,添加/更新/删除子对象并将整个树发送回服务器。Nhibernate足够聪明来确定哪个实体是新的/更新的/删除的。它还只更新更改的实体和更改的属性!如果删除订单,它还会删除所有订单详细信息。

为了完整性,这就是流畅的 nhibernate 映射:

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {
        Schema("YOURSCHEMA");
        Table("CUSTOMER");
        Id(x => x.Id, "ID").GeneratedBy.Assigned();
        Map(x => x.Name, "NAM");
        Map(x => x.City, "CITY");
        HasMany(x => x.Orders)
            .KeyColumn("CUSTOMER_ID")
            .Not.LazyLoad()
            .Inverse()
            .Cascade.AllDeleteOrphan();


        DynamicUpdate();
    }
}

public class OrderMap : ClassMap<Order>
{
    public OrderMap()
    {
        Schema("YOURSCHEMA");
        Table("CUSTOMER_ORDER");
        Id(x => x.Id, "ID").GeneratedBy.Assigned();
        Map(x => x.OrderDate, "ORDER_DATE");
        HasMany(x => x.OrderDetails)
            .KeyColumn("ORDER_ID")
            .Not.LazyLoad()
            .Inverse()
            .Cascade.AllDeleteOrphan();

        References<Customer>(x => x.Customer, "CUSTOMER_ID");
        DynamicUpdate();
    }
}

public class OrderDetailMap : ClassMap<OrderDetail>
{
    public OrderDetailMap()
    {
        Schema("YOURSCHEMA");
        Table("ORDER_DETAIL");
        Id(x => x.Id, "ID").GeneratedBy.Assigned();
        Map(x => x.ProductName, "PRODUCT_NAME");
        Map(x => x.Amount, "AMOUNT");

        References<Order>(x => x.Order, "ORDER_ID");
        DynamicUpdate();
    }
}

DynamicUpdate()用于让nhibernate只更新改变的属性。 您现在只需要使用ISession.Merge(customer)功能可以正确保存所有内容。

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

ServiceStack.Text序列化循环引用 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐

  • 汇总不同聚合级别的数据 - R 和 tidyverse

    我正在创建一堆基本状态报告 我发现乏味的一件事是向我的所有表添加总行 我目前正在使用 Tidyverse 方法 这是我当前代码的示例 我正在寻找的是默认包含几个不同级别的选项 load into RStudio viewer not req
  • 改造以解析具有不定数量的对象名称的 json

    我正在使用 Retrofit 来处理 REST API 调用 我有一个返回以下 json 的 REST API MyObject 43508 field1 4339 field2 val field3 15 field4 586 78 10
  • Ruby XML 到 JSON 转换器?

    Ruby 中有一个库可以将 XML 转换为 JSON 吗 一个简单的技巧 首先你需要gem install json 那么当使用 Rails 时你可以这样做 require json require active support core
  • 重载强制转换运算符时出现歧义

    考虑下面的示例代码 include
  • Heartbleed bug 是 C 语言中经典缓冲区溢出漏洞的表现吗?

    在我们关于安全性的第一堂 CS 讲座中 我们了解了 C 的问题 即不检查所谓的缓冲区长度 以及利用此漏洞的不同方式的一些示例 在这种情况下 看起来这是一个恶意读取操作的情况 应用程序只是读出了多少字节的内存 我断言 Heartbleed b
  • Objective-C 依赖项的弃用警告

    使 Swift var 向后兼容 Objective C 我有一个 Objective C 类 已转换为 Swift 我所有的测试都通过了 但我想通过添加一个弃用警告来更新以通知用户将下游依赖项更新到 Swift 版本的 var 来进一步优
  • 为什么更好的隔离级别意味着 SQL Server 更好的性能

    在测量查询性能时 我发现隔离级别和运行时间之间存在依赖关系 这让我感到惊讶 READUNCOMMITTED 409024 READCOMMITTED 368021 REPEATABLEREAD 358019 SERIALIZABLE 348
  • 如何修改移动设备和选项卡的引导轮播

    我正在使用引导滑块 在桌面上 它有三张幻灯片 每张幻灯片有 4 个图块 在选项卡上 它们必须是 4 张幻灯片 每张幻灯片 3 个图块 在移动设备上 需要有 12 张不同的幻灯片 我正在考虑实现这一点的最有效和最优化的方法 Option 1
  • Hibernate3 与 Oracle 12c

    我们正在将 oracle 从 11g 升级到 12c 我的应用程序正在使用hibernate3 jar这是 3 6 8 最终版本 与 11g 配合使用效果很好Oracle10gDialect但是当我连接到 12c 数据库时出现以下错误 我还
  • 使用 ezplot 在 MATLAB 中的同一个图形上绘制两个函数

    我想使用 ezplot 在 MATLAB 中绘制以下三个函数 但我希望这些函数位于同一张图上 以便轻松解释差异 这可能吗 如果是这样怎么办 这三个功能是 x 3 x 5 x 7 thanks 神秘的xhobo 只需使用hold on将它们连
  • 什么是缩放图像以及如何在网页中提供缩放图像?

    当我在 google PageSpeed 中运行测试页面时 我发现了一些警告 例如提供缩放图像 http man vimal net78 net introduction intro action main THe results were
  • IEnumerable 是如何逆变的?

    这个帖子 http blogs msdn com b brada archive 2005 01 18 355755 aspx https web archive org web 20140417104304 http blogs msdn
  • 如何为 google api php 客户端库设置超时

    我正在使用谷歌的PHP 客户端库 https github com google google api php client构建一个应用程序 有时 Google 需要长达 100 秒的时间来响应 API 请求 我想将套接字超时限制为 30
  • Keras 中的 dropout 行为,rate=1(丢弃所有输入单元)不符合预期

    input0 keras layers Input 32 32 3 name Input0 flatten keras layers Flatten name Flatten input0 relu1 keras layers Dense
  • 如何为 WPF 应用程序创建 chm 帮助文件?

    对于 WPF UI 应用程序 需要创建 CHM 帮助文件 如何创建 chm 帮助文件 首先在ms word中创建文档并将其转换为chm帮助文件 或者任何其他方法 请帮忙 Thanks Ramm I used Sandcastle 帮助文件生
  • Database.BeginTransaction 与 Transactions.TransactionScope [重复]

    这个问题在这里已经有答案了 有什么区别System Transactions TransactionScope和 EF6 的Database BeginTransaction 有人可以举一个小例子 或者只是解释一下当有明显差异时应该使用哪一
  • 获取列位置

    在 Cassandra DB 中 使用有序列族 我知道你能得到切片 但你能得到位置吗 例如 在此数据模型中 我保存如下分数 Scores 1000 bob lucas 900 tim 800 mario 知道用户的分数为 900 并且他的昵
  • 传递Physics2DShapeQueryParameters 层进行检查

    我目前正在为我的 2D 自上而下游戏开发一个构建系统 最后一步是检查是否有任何物体 例如树或玩家 阻碍了物品的放置 经过一些研究后 我发现使用Physics2DShapeQueryParameters 是正确的方法 我唯一的问题是我不知道如
  • 仅克隆雪花元数据

    我想克隆 Snowflake 数据库的外壳 仅元数据 无数据 这可能吗 我检查了文档并没有找到解决方案 如果您只是想获取现有数据库的空壳 则可以克隆整个数据库 然后编写脚本截断数据库中存在的所有表 克隆不会添加任何数据 并且克隆上的截断速度
  • ServiceStack.Text序列化循环引用

    我需要像这样序列化对象图 public class A public B Link1 get set public class B public A Link2 get set 这样json只得到两个实例 但又被正确反序列化了 例如 使用元