2016-11-24 13 views
4

私はAvroと協力しており、GenericRecordがあります。そこからclientIddeviceNameholderを抽出したいと思います。 Avroスキーマでは、clientIdはInteger、deviceNameはString、holderはMapです。アブロスキーマ内GenericRecordから型付き値を取得するには?

{ 
    "name" : "deviceName", 
    "type" : [ "null", "string" ], 
    "doc" : "test" 
} 

holder:アブロスキーマ内

{ 
    "name" : "clientId", 
    "type" : [ "null", "int" ], 
    "doc" : "hello" 
} 

deviceName:アブロスキーマ内

clientId

{ 
    "name" : "holder", 
    "type" : { 
     "type" : "map", 
     "values" : "string" 
    } 
} 

私の質問は - 何ですかタイプされた値を取得するための推奨された方法オブジェクト?

​​はGenericRecordであり、avroスキーマを取得できます。これは私が現在行っていることです。すべてをStringとして抽出しています。しかし、どうやって代わりに型付きの値を得ることができますか?何か方法はありますか?私は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 
    } 

だから私はGenericRecordからJavaマップMap<String, String>として文字列として整数、deviceNameとしてclientIdholderを抽出したいですか?それをする最善の方法は何ですか?一般的なレコードとスキーマで与えられたすべての型付き変換を行うユーティリティを書くことはできますか?

+0

3種類の 'payload.get'呼び出しから返されるオブジェクトのタイプは何ですか? – qxz

+0

@qxz意味ですか?理解できませんでした。それはオブジェクトとしてすべてを返し、あなたはそれを見えるようにキャストしなければなりません。ペイロードからスキーマを使用し、結果を変換して返すユーティリティを書くことができると思います。 – john

+0

それぞれについて、 'payload.get(" ... ")。getClass()を印刷してみてください。オブジェクトの型を見るためにgetCanonicalName()を呼び出す – qxz

答えて

1

あなたはintIntegerに、Utf8にごstring値をキャストすることができるはず、とMap<Utf8, Utf8>map。このClassCastException発生させることなく動作するはずです:一般的に

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"); 

    ... 
} 

を、私はあなたがこれらのキャストを行うことができると信じて:

  • プリミティブが(などIntegerDouble、)そのパッケージ版となっ
  • stringなりUtf8
  • bytesjava.nio.ByteBuffer
  • arrayは、あなたがこのアプローチを試みるかもしれjava.util.Map<Utf8, [value type]>
1

なりjava.util.Collection

  • mapになります。堅牢な実装の場合は、コードを考慮する必要がありますgeneration using schema compilation.

    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; 
         } 
        } 
    
    } 
    
  • 関連する問題