2014-12-19 19 views
7

Tôi đang cố gắng chuyển đổi một chuỗi Json thành một đối tượng Java chung, với một lược đồ Avro.Chuỗi Json đến đối tượng Java Avro

Dưới đây là mã của tôi.

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

Tôi nhận được "org.apache.avro.AvroTypeException: Công đoàn bắt đầu dự kiến. Got VALUE_NUMBER_FLOAT" Ngoại lệ.

Cùng một mã hoạt động, nếu tôi không có công đoàn trong lược đồ. Ai đó có thể giải thích và đưa cho tôi một giải pháp.

+0

Từ http://avro.apache.org/docs/1.7.6/spec.html#json_encoding, tôi hiểu rằng mã hóa Json cho các công đoàn là khác nhau, nhưng tôi đang cố gắng tìm ra nếu có bất kỳ cách nào, theo đó Tôi có thể chuyển đổi chuỗi json thành đối tượng. –

+1

FYI, quá tải của 'jsonDecoder()' chấp nhận một chuỗi json; không cần phải chuyển đổi nó thành luồng. – jaco0646

Trả lời

0

Giản đồ của bạn không khớp với giản đồ của chuỗi json. Bạn cần phải có một lược đồ khác mà không có một liên minh ở vị trí của lỗi mà là một số thập phân. Lược đồ như vậy sau đó nên được sử dụng làm lược đồ nhà văn trong khi bạn có thể tự do sử dụng lược đồ kia làm lược đồ trình đọc.

+0

Cách khác, hãy cho Avro biết bạn đang sử dụng cái nào, như sau: 'Chuỗi json =" {\ "foo \": {\ "gấp đôi \": 30.1}, \ "thanh \": {\ "gấp đôi \" : 60.2}} ";' – Keegan

+0

Đó sẽ là cách mà Avro sẽ tuần tự hóa bản ghi với lược đồ đã cho. – miljanm

+0

Cảm ơn Miljanm và Keegan. Có, tôi hiểu rằng mã hóa json cho các công đoàn khác với avro.apache.org/docs/1.7.6/spec.html#json_encoding. Nhưng tôi đã tìm kiếm một thư viện mã nguồn mở, có thể thay đổi nội bộ chuỗi json của tôi thành lược đồ cụ thể của avro rồi phân tích nó. là một cái gì đó như thế có sẵn? –

6

Nhờ Reza. Tôi tìm thấy trang web này. Nó giới thiệu làm thế nào để chuyển đổi một chuỗi Json thành một đối tượng avro.

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

Chìa khóa mã của ông là:

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

Mã này sẽ không giải quyết được sự cố. Điều này không hoạt động khi lược đồ chứa các công đoàn. – deepak

3

Với Avro 1.4.1, công trình này:

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

Có thể cần một số tinh chỉnh cho các phiên bản Avro sau.

Các vấn đề liên quan