【问题标题】:Using JSON serialization as a persistence mechanism instead of RDB使用 JSON 序列化作为持久化机制而不是 RDB
【发布时间】:2009-07-03 11:08:13
【问题描述】:

我正在考虑在我的下一个项目中丢弃我的数据库以简化开发/演进。

做到这一点的一种方法是根本不离开对象领域并通过某种序列化来保存我的对象。能够在应用程序关闭时编辑初始对象状态会很不错,因此像 JSON 这样的格式会很棒。

问题在于 JSON 工具(如 Java Jackson),或者更确切地说是 JSON 本身,无法保留引用,因此在反序列化对象图之后,我可以获得比序列化之前更多的实例——每个引用都指向同一个对象获取新实例。

我注意到JSPON,但它似乎没有生命。

您如何看待这种方法 - 是不是太简单了?或者也许我应该使用一些 OODB(尽管它会产生额外的配置开销,并且我想保持简单)。

【问题讨论】:

    标签: c# java json persistence


    【解决方案1】:

    大多数 simple 可移植序列化程序(xml、json、协议缓冲区)都是 tree 序列化程序(不是 graph 序列化程序),所以你稍微看看这个问题...

    您也许可以尝试使用不需要引用的 DTO 树?即代替:

    Parent -(children)-> Child
           <--(parent)--
    

    你有(在 DTO 级别):

    Parent {Key="abc"} -(child keys)-> {string}
    Child {Key="def"} -(parent key)-> {string}
    

    这应该可以与任何树序列化程序一起使用;但它确实需要额外的(手动)处理。

    有基于图形的序列化器,例如 .NET 的 DataContractSerializer(启用图形模式;默认情况下禁用);但这不是便携式的。

    【讨论】:

    • 感谢适当的区分,它清除了我的想法。我发现 Xstream (xstream.codehaus.org/graphs.html) 可以处理图形序列化(我不确定它是否也可以在 JSON 模式下,但我可以使用 XML)。
    【解决方案2】:

    假设您控制序列化,引用问题应该足够简单,可以解决 - 您只需保存为每个对象分配 id 的对象,然后根据这些 id 保存引用。

    但是,虽然我认为您会得到一个简单的版本,但我认为您会遇到问题。想到的事情是:

    • 随着代码的发展和类的变化会发生什么?
    • 您将如何支持查询操作,尤其是索引以加快查询速度?
    • 您将如何管理并发访问?
    • 您将如何管理事务?
    • 它将如何扩展?

    我不认为这些问题是不可克服的,但恕我直言,关系数据库是它们基于多年开发和野外使用的方式,而我所看到的 OODB 目前还不是一个现实的命题。

    此外,关系数据库提供的基于集合的逻辑非常适合解决一整类问题,更不用说 SQL 在优化您加载的数据集方面的强大功能了,这在对象世界中并不容易.如今,现代 ORM 让生活变得如此轻松,我当然希望将自己限制在任何一个领域。

    【讨论】:

    • 我同意您提到的问题,尽管我正在考虑的特定项目无法处理其中的大多数问题,因为它不必扩展,因此可以通过锁定来解决并发问题。此外不会有很多数据,因此性能/索引也不会成为问题。交易 - 公平点,但也不需要模式演变 - 真的,与查询问题有关(特别是没有简单的方法来轻松地进行大规模更新)。不过,LINQ 和追随者会让事情变得更容易。
    • @deadbeef - 不管怎样,这肯定会是一个有趣的练习,所以试着回帖让我们都知道它是怎么回事。
    【解决方案3】:

    Json.NET最新版支持serializing references

    string json = JsonConvert.SerializeObject(people, Formatting.Indented,
      new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
    //[
    //  {
    //    "$id": "1",
    //    "Name": "James",
    //    "BirthDate": "\/Date(346377600000)\/",
    //    "LastModified": "\/Date(1235134761000)\/"
    //  },
    //  {
    //    "$ref": "1"
    //  }
    //]
    
    List<Person> deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json,
      new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
    
    Console.WriteLine(deserializedPeople.Count);
    // 2
    
    Person p1 = deserializedPeople[0];
    Person p2 = deserializedPeople[1];
    
    Console.WriteLine(p1.Name);
    // James
    
    Console.WriteLine(p2.Name);
    // James
    
    bool equal = Object.ReferenceEquals(p1, p2);
    // true
    

    【讨论】:

      【解决方案4】:

      我发现this SO 问题很有帮助。 XStream 似乎通过在查找下一个引用时使用树结构中的相对路径到第一个引用来处理引用,即使对于 json 也是如此(请参阅here)。

      Simple 显然可以处理更复杂的对象图,但 XStream 似乎更受欢迎,JSON 并且可能会满足我的需求(我不会有循环引用)。

      【讨论】:

      • 但是请注意,XStream 确实是一个基于 XML 的对象序列化器;因此,虽然它确实支持 JSON 兼容性,但它通过 JSON->XML 转换器 (Jettison),因此 JSON 可能具有的任何大小或性能优势都会丢失。所以我建议只使用 XML,如果与 XStream 一起使用(这是一个很好的对象序列化工具,这就是它的设计目的)。
      【解决方案5】:

      itemscript 项目提出了一种基于 JSON 的模式语言。 itemscript 模式描述数据类型。 itemscript JAM 是在 itemscript 中开发的应用标记。

      参考实现包括一个 GWT 客户端 (Item Lens) 和一个持久存储 JSON 数据的列存储 (Item Store)。

      【讨论】:

        【解决方案6】:

        只要您不离开 .NET 领域,为什么不使用 .NET 提供的序列化机制呢?它可以轻松地将您的对象图(包括私有字段)序列化为二进制 blob,然后再返回。还有一个用于序列化 XML 和从 XML 序列化的内置机制,尽管这在涉及私有字段和内容时有一些限制(尽管您可以解决这个问题)。还有一些属性指定某些字段较新并且可能不在序列化流中。您必须自己处理它们为 NULL,但是 - 无论如何您都必须这样做。

        补充:啊,是的,忘了提 - 我说的是System.Runtime.Serialization.Formatters.Binary.BinaryFormatter类。

        【讨论】:

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