我正在使用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
的键。
在CharSequence
中使用Map
作为关键非常不方便,有没有办法为Apache Avro中的String
生成Map
类型键?< / p>
P.S。
问题在于,例如dataMap.containsKey("SOME_KEY")
将返回false
,即使有那样的密钥,只是因为它是CharSequence
。此外,使用现有密钥放置一个映射条目不会重新使用旧密钥。这就是为什么我说使用CharSequence
作为关键是不方便的。
答案 0 :(得分:8)
This JIRA discussion是相关的。仍然使用CharSequence的要点是向后兼容性。
就像Charles Forsythe所指出的那样,通过在模式中设置字符串属性,已经为必要时添加了一个变通方法。
{ "type": "string", "avro.java.string": "String" }
这里的默认类型是他们自己的Utf8类。除了手动规范和the pom.xml setting之外,还有一个avro-tools编译选项,-string
选项:
java -jar avro-tools.1.7.5.jar compile -string schema /path/to/schema .
答案 1 :(得分:6)
显然,Avro 1.6中存在解决此问题的方法。您在项目的POM文件中指定字符串类型:
<stringType>String</stringType>
本期中提到的是AVRO-803 ...虽然插件的网络文档没有反映这一点。
答案 2 :(得分:4)
显然,默认情况下,Avro使用CharSequence
。我找到了a way to configure it to convert to String
从Avro 1.6.0开始,可以选择让Avro始终执行到String的转换。有几种方法可以实现这一目标。第一种是将模式中的avro.java.string属性设置为String:
{ "type": "string", "avro.java.string": "String" }
我没有测试过这个。
答案 3 :(得分:2)
无论是否可以强制Avro使用String
,直接使用CharSequence
是一个糟糕的实现,因为CharSequence
不是Comparable<CharSequence>
,甚至不指定两个相同序列的相等性。我建议将其视为针对Avro的错误。
答案 4 :(得分:0)
快速解决方案(值类型可以是其他对象,现在我是):
Map<String, String> convertToStringMap(Map<CharSequence, CharSequence> map){
if (null == map){
return null;
}
HashMap<String, String> result = new HashMap<String, String>();
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;
}
答案 5 :(得分:0)
我认为明确地将String转换为Utf8会起作用。 “some_key” - &gt;新的Utf8(“some_key”)并使用它作为地图的关键。