2014-12-19 32 views
7

Bir Json dizesini bir Avro Şema ile genel bir Java nesnesine dönüştürmeye çalışıyorum.Json Nesne Java Nesnesi Avro

Kodum aşağıda. ": Beklenen başlangıç ​​birliği Got VALUE_NUMBER_FLOAT org.apache.avro.AvroTypeException." İstisna

String json = "{\"foo\": 30.1, \"bar\": 60.2}"; 
String schemaLines = "{\"type\":\"record\",\"name\":\"FooBar\",\"namespace\":\"com.foo.bar\",\"fields\":[{\"name\":\"foo\",\"type\":[\"null\",\"double\"],\"default\":null},{\"name\":\"bar\",\"type\":[\"null\",\"double\"],\"default\":null}]}"; 

InputStream input = new ByteArrayInputStream(json.getBytes()); 
DataInputStream din = new DataInputStream(input); 

Schema schema = Schema.parse(schemaLines); 

Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); 

DatumReader<Object> reader = new GenericDatumReader<Object>(schema); 
Object datum = reader.read(null, decoder); 

alıyorum.

Şemada sendikalarım yoksa, aynı kod çalışır. Birisi lütfen bana bir çözüm sunabilir ve verebilir.

+0

http://avro.apache.org/docs/1.7.6/spec.html#json_encoding adresinden, sendikaları kodlayan Json'un farklı olduğunu anlıyorum, ancak herhangi bir yolun olup olmadığını anlamaya çalışıyorum. Json dizesini nesnelere dönüştürebilirim. –

+1

FYI, jsonDecoder() 'ın bir aşırı yükü bir json String'i kabul eder; Onu bir Akışa dönüştürmeye gerek yoktur. – jaco0646

cevap

0

Şemanız, json dizesinin şemasıyla eşleşmiyor. Hatanın yerine ondalık sayı olmayan farklı bir şemaya sahip olmanız gerekir. Bu şema daha sonra yazar şeması olarak kullanılmalı, diğeri ise okuyucu şeması olarak özgürce kullanabilirsiniz.

+0

Alternatif olarak, kullandığınız Avro'ya şu şekilde bildirin: 'String json =" {\ "foo \": {\ "double \": 30.1}, \ "bar \": {\ "double \" : 60.2}} "; – Keegan

+0

Avro'nun, verilen şema ile rekoru serileştirme yolu bu olurdu. – miljanm

+0

Teşekkürler Miljanm ve Keegan. Evet, sendikaları kodlayan json'un avro.apache.org/docs/1.7.6/spec.html#json_encoding adresinden farklı olduğunu anlıyorum. Ama ben açık kaynak kodlu bir kütüphane arıyordum, bu da json dizgimi avroya özgü şemaya içsel olarak değiştirebiliyor ve sonra onu ayrıştırabiliyor. böyle bir şey mi? –

6

Rıza sayesinde. Bu web sayfasını buldum. Bir Json dizesinin avro nesnesine nasıl dönüştürüleceğini açıklar.

http://rezarahim.blogspot.com/2013/06/import-org_26.html

onun kod anahtarı:

static byte[] fromJsonToAvro(String json, String schemastr) throws Exception { 
    InputStream input = new ByteArrayInputStream(json.getBytes()); 
    DataInputStream din = new DataInputStream(input); 

    Schema schema = Schema.parse(schemastr); 

    Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); 

    DatumReader<Object> reader = new GenericDatumReader<Object>(schema); 
    Object datum = reader.read(null, decoder); 

    GenericDatumWriter<Object> w = new GenericDatumWriter<Object>(schema); 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 

    Encoder e = EncoderFactory.get().binaryEncoder(outputStream, null); 

    w.write(datum, e); 
    e.flush(); 

    return outputStream.toByteArray(); 
} 

String json = "{\"username\":\"miguno\",\"tweet\":\"Rock: Nerf paper, scissors is fine.\",\"timestamp\": 1366150681 }"; 

String schemastr ="{ \"type\" : \"record\", \"name\" : \"twitter_schema\", \"namespace\" : \"com.miguno.avro\", \"fields\" : [ { \"name\" : \"username\", \"type\" : \"string\", \"doc\" : \"Name of the user account on Twitter.com\" }, { \"name\" : \"tweet\", \"type\" : \"string\", \"doc\" : \"The content of the user's Twitter message\" }, { \"name\" : \"timestamp\", \"type\" : \"long\", \"doc\" : \"Unix epoch time in seconds\" } ], \"doc:\" : \"A basic schema for storing Twitter messages\" }"; 

byte[] avroByteArray = fromJsonToAvro(json,schemastr); 

Schema schema = Schema.parse(schemastr); 
DatumReader<Genericrecord> reader1 = new GenericDatumReader<Genericrecord>(schema); 

Decoder decoder1 = DecoderFactory.get().binaryDecoder(avroByteArray, null); 
GenericRecord result = reader1.read(null, decoder1); 
+0

Bu kod sorunu çözmeyecektir. Şema, sendika içerdiğinde bu çalışmaz. – deepak

3

Avro 1.4.1 ile bu işleri:

private static GenericData.Record parseJson(String json, String schema) 
    throws IOException { 
    Schema parsedSchema = Schema.parse(schema); 
    Decoder decoder = new JsonDecoder(parsedSchema, json); 

    DatumReader<GenericData.Record> reader = 
     new GenericDatumReader<>(parsedSchema); 
    return reader.read(null, decoder); 
} 

sonraki Avro sürümleri için bazı ince ayarları ihtiyacım olabilir.