递归数据类型,如树作为Avro架构

时间:2017-10-19 21:51:35

标签: protocols avro recursive-datastructures

阅读https://avro.apache.org/docs/current/spec.html它说模式必须是以下之一:

  • 一个JSON字符串,命名一个已定义的类型。
  • 一个JSON对象,格式如下: {"type": "typeName" ...attributes...}其中typeName是a 原始或派生类型名称,如下所述。属性不是 允许将本文档中定义的元数据作为元数据,但不得使用 影响序列化数据的格式。
  • 一个JSON数组,代表一个 嵌入式类型的联合。

我想要一个描述树的模式,使用树的递归定义:

  • 具有值(例如,整数)和树列表​​(子项)的节点
  • 具有值
  • 的叶子

我最初的尝试看起来像:

{
  "name": "Tree",
  "type": [
    {
      "name": "Node",
      "type": "record",
      "fields": [
        {
          "name": "value",
          "type": "long"
        },
        {
          "name": "children",
          "type": { "type": "array", "items": "Tree" }
        }
      ]
    },
    {
      "name": "Leaf",
      "type": "record",
      "fields": [
        {
          "name": "value",
          "type": "long"
        }
      ]
    }
  ]
}

但Avro编译器拒绝这一点,抱怨没有类型{"name":"Tree","type":[{"name":"Node"...。似乎Avro不喜欢顶层的联盟类型。我猜测这属于上述规则"模式必须是...... JSON对象之一..其中typeName是基本类型或派生类型名称。"我不确定"派生类型名称"虽然。起初我认为它与复杂类型相同"但这包括工会类型..

无论如何,将其更改为更复杂的定义:

{
  "name": "Tree",
  "type": "record",
  "fields": [{
    "name": "ctors",
    "type": [
      {
        "name": "Node",
        "type": "record",
        "fields": [
          {
            "name": "value",
            "type": "long"
          },
          {
            "name": "children",
            "type": { "type": "array", "items": "Tree" }
          }
        ]
      },
      {
        "name": "Leaf",
        "type": "record",
        "fields": [
          {
            "name": "value",
            "type": "long"
          }
        ]
      }
    ]
  }]
}

有效,但现在我有一个奇怪的记录只有一个字段,其唯一目的是让我定义我想要的顶级联合类型。

这是获得Avro我想要的唯一方法还是有更好的方式?

谢谢!

2 个答案:

答案 0 :(得分:2)

我只是偶然发现想要定义递归联合的同一个问题。我对一个比你复杂的解决方案更清晰的解决方案感到非常悲观,因为目前没有办法命名一个联合,因此在构造它时无法以递归的方式引用它,请参阅open ticket

答案 1 :(得分:0)

如果您将Tree表示为一个节点,而将Leaf表示为一个具有空子列表的节点,则可以完全避免命名的并集问题,并且只需一个递归即可类型:

{
  "type": "record",
  "name": "TreeNode",
  "fields": [
    {
      "name": "value",
      "type": "long"
    },
    {
      "name": "children",
      "type": { "type": "array", "items": "TreeNode" }
    }
  ]
}

现在,您的三种类型TreeNodeLeaf统一为一种类型TreeNode,并且没有Node和{的并集{1}}。