7

我正在使用这个 Avro 模式:

价格状态.avsc

{
    "namespace": "com.company.model",
    "name": "Product",
    "type": "record",
    "fields": [
        {
            "name": "product_id",
            "type": "string"
        },
        {
            "name": "sale_prices",
            "type": {
                "name": "sale_prices",
                "type": "record",
                "fields": [
                    {
                        "name": "default",
                        "type": {
                            "name": "default",
                            "type": "record",
                            "fields": [
                                {
                                    "name": "order_by_item_price_by_item",
                                    "type": [
                                        "null",
                                        {
                                            "name": "markup_strategy",
                                            "type": "record",
                                            "fields": [
                                                {
                                                    "name": "type",
                                                    "type": {
                                                        "name": "type",
                                                        "type": "enum",
                                                        "symbols": ["margin", "sale_price"]
                                                    }
                                                }
                                            ]
                                        }
                                    ]
                                },
                                {"name": "order_by_item_price_by_weight", "type": ["null", "string"]},
                                {"name": "order_by_weight_price_by_weight", "type": ["null", "string"]}
                            ]
                        }
                    }
                ]
            }
        }
    ]
}

它在这个网站上正确验证,所以我假设架构是有效的。

我在构建 JSON 文件时遇到问题,然后应该使用上述模式对其进行编码。

我正在使用这个 JSON 进行一些测试:

测试.json

{
    "product_id": "123",
    "sale_prices": {
        "default": {
            "order_by_item_price_by_item": {
                "markup_strategy": {
                    "type": {"enum": "margin"}
                }
            },
            "order_by_item_price_by_weight": null,
            "order_by_weight_price_by_weight": null
        }
    }
}

跑步时java -jar avro-tools-1.8.2.jar fromjson --schema-file prices-state.avsc test.json我得到:

线程“主”org.apache.avro.AvroTypeException 中的异常:未知联合分支 markup_strategy

我在这里读到,由于 JSON 编码,我必须将东西包装在 union 中,所以我尝试了不同的组合,但似乎没有一个有效。

4

2 回答 2

15

这是一个命名空间解析问题。以这个简化的模式为例:

测试.avsc

{
    "name": "Product",
    "type": "record",
    "fields": [
        {
            "name": "order_by_item_price_by_item",
            "type": [
                "null",
                {
                    "type": "record",
                    "name": "markup_strategy",
                    "fields": [{
                        "name": "type",
                        "type": {
                            "name": "type",
                            "type": "enum",
                            "symbols": ["margin", "sale_price"]
                        }
                    }]
                }
            ]
        }
    ]
}

使用以下 JSON 验证就好了

测试.json

{
    "order_by_item_price_by_item": {
        "markup_strategy": {
            "type": "margin"
        }
    }
}

现在,如果您要在架构之上添加一个命名空间,例如

测试.avsc

{
    "namespace": "test",
    "name": "Product",
    "type": "record",
    "fields": [
    ...

然后你需要改变你的test.json或者你会得到

线程“主”org.apache.avro.AvroTypeException 中的异常:未知联合分支 markup_strategy

final_test.json

{
    "order_by_item_price_by_item": {
        "test.markup_strategy": {
            "type": "margin"
        }
    }
}

因此,当在联合类型中并且您正在对使用用户指定名称的 Avro 的命名类型(记录、固定或枚举)进行 JSON 编码时,则该类型的名称也需要在名称前面加上命名空间名称以进行解析。

更多关于命名空间JSON 编码

于 2018-04-20T10:39:59.263 回答
0

Francesco 的回答很好,并解释了这个问题!
以防万一任何人(甚至我未来的自己)需要另一个带有可选字段和命名空间的示例:

  1. 架构 - StackOverflowSchema.avsc
{
  "type": "record",
  "name": "StackOverflowExampleSchema",
  "namespace": "com.schemata.stackoverflow",
  "fields": [
    {
      "name": "exampleEntity",
      "type": {
        "type": "record",
        "name": "ExampleEntity",
        "namespace": "com.stackoverflow",
        "fields": [
          {
            "name": "description",
            "type": ["null", "string"]
          },
          {
            "name": "currentAmount",
            "type": {
              "type": "record",
              "name": "MonetaryAmount",
              "namespace": "com.acme.common",
              "fields": [
                {
                  "name": "currencyCode",
                  "type": ["null", {
                    "type": "enum",
                      "name": "CurrencyCode",
                      "symbols": ["AED", "USD"],
                      "default": "USD"
                    }
                  ]
                },
                {
                  "name": "amount",
                  "type": {
                    "type": "int"
                  }
                }
              ]
            }
          },
          {
            "name": "totalAmount",
            "type": ["null", "com.acme.common.MonetaryAmount"]
          }
        ]
      }
    }
  ]
}
  1. 示例文件 - stackoverflow.json
{
  "exampleEntity": {
    "description": {
      "string": "some optional description"
    },
    "currentAmount":{
      "amount": 10",
      "currencyCode": {
        "com.acme.common.CurrencyCode": "USD"
      }
    },
    "totalAmount": {
      "com.acme.common.MonetaryAmount": {
        "amount": 20,
        "currencyCode": {
          "com.acme.common.CurrencyCode": "USD"
        }
      }
    }
  }
}

两者currentAmount都有totalAmount类型com.acme.common.MonetaryAmount
前者是必填字段,后者可以是null
同样在MonetaryAmount我们需要的( amount) 和可选的( currencyCode) 中。
下面的命令产生 avro 消息:

java -jar avro-tools-1.11.0.jar fromjson --schema-file ./StackOverflowSchema.avsc stackoverflow.json > stackoverflow.avro
于 2021-11-20T18:46:35.127 回答