Apache Avro:map使用CharSequence作为密钥
我正在使用Apache Avro 。
我的架构有地图类型:
{"name": "MyData", "type" : {"type": "map", "values":{ "type": "record", "name": "Person", "fields":[ {"name": "name", "type": "string"}, {"name": "age", "type": "int"}, ] } } }
在编译模式之后,生成的Java类使用CharSequence
作为Map
MyData
的键 。
在Map
使用CharSequence
作为键是非常不方便的,有没有办法在Apache Avro中为Map
生成String
类型键?
PS
问题是,例如dataMap.containsKey("SOME_KEY")
将返回false
即使有那样的键,只是因为它是CharSequence
。 此外,使用现有密钥放置映射条目不会重新使用旧密钥。 这就是为什么我说使用CharSequence
作为关键是不方便的。
显然,Avro 1.6中存在解决此问题的方法。 您在项目的POM文件中指定字符串类型:
String
本期中提到的是AVRO-803 ……尽管插件的Web文档没有反映出这一点。
这次JIRA讨论是相关的。 仍然使用CharSequence的要点是向后兼容性 。
就像Charles Forsythe所指出的那样,通过在模式中设置字符串属性,已经为必要时添加了一个变通方法。
{ "type": "string", "avro.java.string": "String" }
这里的默认类型是他们自己的Utf8类。 除了手动规范和pom.xml设置之外 ,还有一个avro-tools编译选项, -string
选项:
java -jar avro-tools.1.7.5.jar compile -string schema /path/to/schema .
显然,默认情况下,Avro使用CharSequence
。 我找到了一种方法来配置它转换为String
从Avro 1.6.0开始,可以选择让Avro始终执行到String的转换。 有几种方法可以实现这一目标。 第一种是将模式中的avro.java.string属性设置为String:
{ "type": "string", "avro.java.string": "String" }
我没有测试过这个。
无论是否可以强制Avro使用String
,直接使用CharSequence
是一个糟糕的实现,因为CharSequence
不是Comparable
,甚至不指定两个相同序列的相等性。 我建议将此作为针对Avro的错误提交。
一个快速的解决方案(值类型可能是其他对象,现在我是):
Map convertToStringMap(Map map){ if (null == map){ return null; } HashMap result = new HashMap(); for(CharSequence key: map.keySet()){ CharSequence k_value = map.get(key); String s_key = key.toString(); String s_value = k_value.toString(); result.put(s_key, s_value); } return result; }
我认为明确地将String转换为Utf8将起作用。 “some_key” – >新的Utf8(“some_key”)并将其用作地图的关键字。