2014-04-08 14 views
6

Próbuję napisać bardzo prosty schemat avro (łatwy, ponieważ właśnie wskazuję mój bieżący numer), aby zapisać plik danych avro na podstawie danych przechowywanych w formacie json. Sztuczka polega na tym, że jedno pole jest opcjonalne, a jedno z avrotools lub ja nie robi tego dobrze.Generowanie avro schematu z opcjonalnymi wartościami

Celem nie jest napisanie własnego serializera, ostatecznym celem będzie posiadanie tego we flume, jestem we wczesnym stadium.

Dane (prac), w pliku o nazwie so.log:

{ 
    "valid": {"boolean":true} 
, "source": {"bytes":"live"} 
} 

schematu, w pliku o nazwie so.avsc:

{ 
    "type":"record", 
    "name":"Event", 
    "fields":[ 
     {"name":"valid", "type": ["null", "boolean"],"default":null} 
    , {"name":"source","type": ["null", "bytes"],"default":null} 
    ] 
} 

mogę łatwo wygenerować plik Avro za pomocą następującego polecenia:

java -jar avro-tools-1.7.6.jar fromjson --schema-file so.avsc so.log 

Jak dotąd tak dobrze. Chodzi o to, że „źródło” jest opcjonalny, więc spodziewałbym następujące dane zachowują ważność także:

{ 
    "valid": {"boolean":true} 
} 

Ale działa to samo polecenie daje mi błąd:

Exception in thread "main" org.apache.avro.AvroTypeException: Expected start-union. Got END_OBJECT 
at org.apache.avro.io.JsonDecoder.error(JsonDecoder.java:697) 
at org.apache.avro.io.JsonDecoder.readIndex(JsonDecoder.java:441) 
at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:229) 
at org.apache.avro.io.parsing.Parser.advance(Parser.java:88) 
at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:206) 
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:155) 
at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:193) 
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:183) 
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:151) 
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:142) 
at org.apache.avro.tool.DataFileWriteTool.run(DataFileWriteTool.java:99) 
at org.apache.avro.tool.Main.run(Main.java:84) 
at org.apache.avro.tool.Main.main(Main.java:73) 

Próbowałem wiele odmian schematu, nawet rzeczy, które nie są zgodne ze specyfikacją avro. Schemat, który tutaj pokazuję, jest, o ile mi wiadomo, co mówi specyfikacja.

Czy ktoś wie, co robię źle, i jak mogę rzeczywiście mieć elementy opcjonalne bez pisania własnego serializera?

Dzięki

+0

Widząc ten sam problem tutaj, czy znalazłeś jakiś sposób pracy z AvroTools, aby przekonwertować JSON z opcjonalnymi polami do Avro? Jedynym sposobem obejścia tego problemu jest napisanie opakowania, które wstawiłoby domyślne wartości w JSON przed konwersją, ale to wstyd ... – snooze92

+1

Niestety nie miałem szczęścia. W skrócie JSON jest tylko dla wygody i chociaż schemat może mieć wartość domyślną, dokument JSON, który nie ma tej wartości, jest w rzeczywistości nieprawidłowy. Udokumentowałem niektóre [problemy i rozwiązania, które mieliśmy z avro] (http://thisdwhguy.com/2014/10/27/avro-end-to-end-in-hdfs-part-4-problems-and-solutions/) , mam nadzieję, że to pomoże. – Guillaume

+0

Dzięki za odpowiedź, przeczytam Twój artykuł na blogu! Na razie zrezygnowaliśmy z konwersji JSON> Avro. – snooze92

Odpowiedz

1

Według documentation API Java:

using a builder requires setting all fields, even if they are null

python API, z drugiej strony, wydaje się, aby umożliwić pola zerowe być naprawdę otional:

Since the field favorite_color has type ["string", "null"], we are not required to specify this field

W skrócie, ponieważ większość narzędzi jest napisanych java, pola zerowe zwykle muszą być jawnie podane.

Powiązane problemy