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”)并将其用作地图的关键字。