我正在与Avro合作,我有一个通用记录。我想从中提取clientId、deviceName、holder。在Avro模式中,clientId是整数,
deviceName是字符串,
holder是映射。
avro模式中的
clientId
:
{
"name" : "clientId",
"type" : [ "null", "int" ],
"doc" : "hello"
}
avro架构中的设备名称:
{
"name" : "deviceName",
"type" : [ "null", "string" ],
"doc" : "test"
}
avro模式中的持有人:
{
"name" : "holder",
"type" : {
"type" : "map",
"values" : "string"
}
}
我的问题是-检索类型化值的推荐方法是什么,而不是对象?
在下面的代码中,有效负载是GenericRecord,我们可以从中获得avro模式。这就是我现在正在做的,将所有内容提取为字符串。但我如何才能得到类型化的值呢。有什么办法吗?我的意思是,无论avro模式中的数据类型是什么,我只想提取它。
public static void getData(GenericRecord payload) {
String id = String.valueOf(payload.get("clientId"));
String name = String.valueOf(payload.get("deviceName"));
// not sure how to get maps here
}
所以我想提取
clientId
作为整数,deviceName
作为字符串和持有者
作为JavamapMap
您可以尝试这种方法。对于健壮的实现,您应该考虑使用模式编译生成代码。
package stackoverflow;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.avro.AvroTypeException;
import org.apache.avro.Schema;
import org.apache.avro.Schema.Field;
import org.apache.avro.Schema.Type;
import org.apache.avro.generic.GenericData.Record;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.util.Utf8;
import org.junit.Test;
// Just for demonistration; not robust implementation
public class GenericRecordType {
@Test
public void testName() throws Exception {
Schema schema = buildSchema();
GenericRecord record = new Record(schema);
record.put("clientId", 12);
record.put("deviceName", "GlassScanner");
record.put("holder", new HashMap<>());
Integer value = IntField.clientId.getValue(record);
String deviceName = StringField.deviceName.getValue(record);
Map<String, String> mapString = MapOfStringField.holder.getValue(record);
assertThat(deviceName, is("GlassScanner"));
assertThat(value, is(12));
assertThat(mapString.size(), is(0));
}
private Schema buildSchema() {
Field clientId = new Field("clientId", Schema.create(Type.INT), "hello", (Object) null);
Field deviceName = new Field("deviceName", Schema.create(Type.STRING), "hello", (Object) null);
Field holder = new Field("holder", Schema.createMap(Schema.create(Type.STRING)), null, (Object) null);
Schema schema = Schema.createRecord(Arrays.asList(clientId, deviceName, holder));
return schema;
}
public static interface TypedField<T> {
String name();
public T getValue(GenericRecord record);
}
public static enum StringField implements TypedField<String> {
deviceName;
@Override
public String getValue(GenericRecord record) {
String typed = null;
Object raw = record.get(name());
if (raw != null) {
if (!(raw instanceof String || raw instanceof Utf8)) {
throw new AvroTypeException("string type was epected for field:" + name());
}
typed = raw.toString();
}
return typed;
}
}
public static enum IntField implements TypedField<Integer> {
clientId;
private IntField() {
}
@Override
public Integer getValue(GenericRecord record) {
Integer typed = null;
Object raw = record.get(name());
if (raw != null) {
if (!(raw instanceof Integer)) {
throw new AvroTypeException("int type was epected for field:" + name());
}
typed = (Integer) raw;
}
return typed;
}
}
public static enum MapOfStringField implements TypedField<Map<String, String>> {
holder;
@Override
@SuppressWarnings("unchecked")
public Map<String, String> getValue(GenericRecord record) {
Map<String, String> typed = null;
Object raw = record.get(name());
if (raw != null) {
if (!(raw instanceof Map)) {
throw new AvroTypeException("map type was epected for field:" + name());
}
typed = (Map<String, String>) raw;
}
return typed;
}
}
}
您应该能够将您的string
值转换为Utf8
,int
转换为整数
,以及map
到Map
public static void getData(GenericRecord payload) {
int id = (Integer) payload.get("clientId");
String name = payload.get("deviceName").toString(); // calls Utf8.toString
Map<Utf8, Utf8> holder = (Map<Utf8, Utf8>) payload.get("holder");
...
}
总的来说,我相信你可以做这些演员:
原语成为其装箱版本(整数、双精度等)
- 字符串变为Utf8
字节变为java。nio。ByteBuffer
给定GenericRecord,与对象相比,检索类型化值的推荐方法是什么?我们需要强制转换值吗?如果需要,从Avro类型到Java类型的映射是什么?例如,Avro数组==Java集合;和Avro String==Java UTF8。 由于每个GenericRecord都包含它的模式,所以我希望有一种类型安全的方法来检索值。
问题内容: 给定GenericRecord,与对象相比,推荐的检索类型化值的方法是什么?我们是否应该强制转换值,如果是这样,从Avro类型到Java类型的映射是什么?例如,Avro Array == Java Collection ; 和Avro String == Java Utf8 。 由于每个GenericRecord都包含其架构,因此我希望找到一种类型安全的方法来检索值。 问题答案: 阿夫
问题内容: 通常,我见过人们像这样使用类文字: 但是,如果类型是通用类型,例如List,该怎么办?这可以正常工作,但由于应将List参数化,因此发出警告: 那么为什么不添加一个<?>呢?好吧,这会导致类型不匹配错误: 我想像这样的事情会起作用,但这只是一个普通的语法错误: 如何获得Class >静态信息,例如使用类文字? 我可以使用,以摆脱在第一个例子中所造成的非参数使用列表,警告的,但我宁愿不要
问题:我想知道是否可以从DocumentFilter获取JTextfield类型 我读过java文档,搜索了很多,但没有找到任何信息。 需要:我在两个JTextfields上设置了相同的DocumentFilter。当事件发生时,在DocumentFilter的“replace”方法中,我想知道哪个textfield导致了事件。 用例:我有大约15个文本字段(未来可能会增加),我希望对所有这些字段
问题内容: 我使用PDO和MySQL,出于某种原因,当从数据库中获取int类型的值时,PDOStatement返回的是数字的字符串表示形式,而不是数字类型的值。如何防止这种情况发生? 我注意到有一个PDO类的属性:应该可以解决这个问题,但是在尝试修改它时,它抛出一个错误,指出该属性对MySQL驱动程序无效。 查询数据库时,获取字符串而不是数字是否正常? 问题答案: 我不认为可以在PHP 5.2中完
问题内容: 该问题的可接受答案描述了如何在类中创建的实例。这涉及将参数传递给构造函数并从中调用方法。 然后创建的新实例,并传递参数。 如果新类的泛型类型参数不是某个已知类,但它本身是泛型类型参数,该怎么办?假设我还有其他班级,我想从该班级内部创建一个新实例。然后,如果尝试传递,则会收到以下编译器错误: 有没有办法解决? 对我来说触发错误的代码是: 发生错误,是因为我不会写。还有其他传递相同信息的方