org.apache.avro.AvroTypeException: 未知联合分支
org.apache.avro.AvroTypeException: Unknown union branch
我正在使用这个 Avro 模式:
价格-state.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"]}
]
}
}
]
}
}
]
}
它在 this website 上正确验证,所以我假设架构有效。
我在构建 JSON 文件时遇到问题,然后应使用上述架构对其进行编码。
我正在使用这个 JSON 进行一些测试:
test.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
我得到:
Exception in thread "main" org.apache.avro.AvroTypeException: Unknown union branch markup_strategy
我读到 here 由于 JSON 编码,我必须将东西包装在联合内,所以我尝试了不同的组合,但似乎没有一个有效。
这是一个 命名空间 解析问题。以这个简化的模式为例:
test.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 它验证得很好
test.json
{
"order_by_item_price_by_item": {
"markup_strategy": {
"type": "margin"
}
}
}
现在,如果您要在架构之上添加名称空间,例如
test.avsc
{
"namespace": "test",
"name": "Product",
"type": "record",
"fields": [
...
然后你需要改变你的test.json或者你会得到
Exception in thread "main" org.apache.avro.AvroTypeException: Unknown union branch markup_strategy
final_test.json
{
"order_by_item_price_by_item": {
"test.markup_strategy": {
"type": "margin"
}
}
}
因此,当在联合类型中并且您正在 JSON 对使用用户指定名称的 Avro 命名类型(记录、固定或枚举)进行编码时,需要在该类型的名称前添加命名空间名称也用于解析。
更多关于 namespaces and JSON encoding。
Francesco 的回答很好,解释了问题!
以防万一有人(甚至是我未来的自己)
需要另一个带有 optional 字段和 namespaces:
的示例
- 架构 - WhosebugSchema.avsc
{
"type": "record",
"name": "WhosebugExampleSchema",
"namespace": "com.schemata.Whosebug",
"fields": [
{
"name": "exampleEntity",
"type": {
"type": "record",
"name": "ExampleEntity",
"namespace": "com.Whosebug",
"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"]
}
]
}
}
]
}
- 示例文件 - Whosebug.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
中,我们有 required (amount
) 和 optional (currencyCode
).
以下命令生成 avro 消息:
java -jar avro-tools-1.11.0.jar fromjson --schema-file ./WhosebugSchema.avsc Whosebug.json > Whosebug.avro
我正在使用这个 Avro 模式:
价格-state.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"]}
]
}
}
]
}
}
]
}
它在 this website 上正确验证,所以我假设架构有效。
我在构建 JSON 文件时遇到问题,然后应使用上述架构对其进行编码。
我正在使用这个 JSON 进行一些测试:
test.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
我得到:
Exception in thread "main" org.apache.avro.AvroTypeException: Unknown union branch markup_strategy
我读到 here 由于 JSON 编码,我必须将东西包装在联合内,所以我尝试了不同的组合,但似乎没有一个有效。
这是一个 命名空间 解析问题。以这个简化的模式为例:
test.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 它验证得很好
test.json
{
"order_by_item_price_by_item": {
"markup_strategy": {
"type": "margin"
}
}
}
现在,如果您要在架构之上添加名称空间,例如
test.avsc
{
"namespace": "test",
"name": "Product",
"type": "record",
"fields": [
...
然后你需要改变你的test.json或者你会得到
Exception in thread "main" org.apache.avro.AvroTypeException: Unknown union branch markup_strategy
final_test.json
{
"order_by_item_price_by_item": {
"test.markup_strategy": {
"type": "margin"
}
}
}
因此,当在联合类型中并且您正在 JSON 对使用用户指定名称的 Avro 命名类型(记录、固定或枚举)进行编码时,需要在该类型的名称前添加命名空间名称也用于解析。
更多关于 namespaces and JSON encoding。
Francesco 的回答很好,解释了问题!
以防万一有人(甚至是我未来的自己)
需要另一个带有 optional 字段和 namespaces:
- 架构 - WhosebugSchema.avsc
{
"type": "record",
"name": "WhosebugExampleSchema",
"namespace": "com.schemata.Whosebug",
"fields": [
{
"name": "exampleEntity",
"type": {
"type": "record",
"name": "ExampleEntity",
"namespace": "com.Whosebug",
"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"]
}
]
}
}
]
}
- 示例文件 - Whosebug.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
中,我们有 required (amount
) 和 optional (currencyCode
).
以下命令生成 avro 消息:
java -jar avro-tools-1.11.0.jar fromjson --schema-file ./WhosebugSchema.avsc Whosebug.json > Whosebug.avro